随笔分类 - 算法
摘要:题意:FJ希望它的牛做一些清洁工作。有N只牛和T个时间段,每只牛可以承担一段时间内的工作。FJ希望让最小数量的牛覆盖整个T,求出其数量。若无法覆盖整个T,则输出-1.分析:首先要注意T表示T个时间段,也就是说1就是一个时间段,而[1, 2]是两个时间段。在这个问题上,我们要做到的是用最小的牛覆盖整个区间。比较容易想到的是先将牛按开始时间排序,因为如果一开始就覆盖不了那么后续就没有意义可以直接输出-1。贪心选取在满足当前开始时间的前提下,其结束时间的大的牛,因为在满足开始前提下,当然是覆盖得越多越好。可以简单设想如果可以用一只覆盖得比较小的牛来做到最优结果,那么用覆盖得最大的必然也是最优结果。
阅读全文
摘要:题意:有一个烤饼器可以烤r行c列的煎饼,煎饼可以正面朝上(用1表示)也可以背面朝上(用0表示)。一次可将同一行或同一列的煎饼全部翻转。现在需要把尽可能多的煎饼翻成正面朝上,问最多能使多少煎饼正面朝上? 输入:多组输入,每组第一行为二整数r, c (1 ≤ r ≤ 10, 1 ≤ c ≤ 10 000),剩下r行c列表示煎饼初始状态。r=c=0表示输入结束。 输出:对于每组输入,输出最多能使多少煎饼正面朝上。(翻译参考自:http://bbs.byr.cn/#!article/ACM_ICPC/73337?au=Milrivel)分析:这个是二维的穷举,因为列数比较多行数比较少,所以可对行做深度
阅读全文
摘要:题意:给定一个5*5的地图,每个格子上有一个数字。从一个格子出发(上下左右4个方向),走5步将数字连起来可以构造出一个6位数。问该地图可以构造出多少个不同的6位数。分析:可以对每个格子做深度优先遍历,构造出所有数字,但要注意不要重复计数。在这里,我使用了set来保存已构造出的数字,结果就是set中的元素个数。 1 #include 2 #include 3 #include 4 5 using namespace std; 6 7 //输入 8 int a[5][5]; 9 10 set st; //保存已构造的数字11 12 const int dx[...
阅读全文
摘要:题意:已知有N个数分别为1-N,如下图为4个数。相邻两两相加直至只剩下一个数,下图的结果就是16。 3 1 2 4 4 3 6 7 9 16 现在反过来看,告诉你数的个数N和最终结果,问这N个数的初始序列是什么。求出字典序最小的初始序列。上图的初始序列也可以是3 2 1 4,但这不是字典序最小。分析:这题用全排列的方式非常容易做。首先初始化数组为1-N,然后用STL提供的按字典序生成全排列的函数next_permutation即可枚举全排列。对于每一组数,通过计算可以知道它是否能得出已知结果。最先找到的那组数就是字典序...
阅读全文
摘要:题意:给定一组数字,如0, 1, 2, 4, 6, 7,用这些数字组成两个数,并使这两个数之差最小。求这个最小差。在这个例子上,就是204和176,差为28。分析:首先可以想到,这两个数必定是用各一半数量的数字组成的数,如给出6个数,把这6个数分为两组,每组3个,这样组成的数字的差必定比其他方式小。接下来的任务就是穷举所有可能出现的组合,并求出最小差。在这里可以使用STL的next_permutation函数来求给定这组数字的所有排列,并将其分为两组组成数字,然后记录最小差。需要注意第一个数位不能为0。 1 /* 2 input: 3 1 4 0 1 2 4 6 7 5 output: 6 2
阅读全文
摘要:题意:7数码问题。在2×4的棋盘上,摆有7个棋子,每个棋子上标有1至7的某一数字,不同棋子上标的数字不相同。棋盘上还有一个空格(用0表示),与空格相邻(上下左右)的棋子可以移到空格中,该棋子原先位置成为空格。给出一个初始状态(保证可以转移到最终状态),找出一种从初始状态转变成给定最终状态的移动棋子步数最少的移动步骤。输入:多组输入,每组8个数,表示初始状态前四个数为第一行从左到右,后四个数为第二行从左到右。输出:至少需要多少步可以从输入状态到达最终状态(0 1 2 3 4 5 6 7)(题意翻译参考自http://bbs.byr.cn/#!article/ACM_ICPC/73337
阅读全文
摘要:题意:巨大流星雨即将袭来。每个流星会对击中的地方以及周围(上下左右四格)造成破坏。Bessie开始时位于(0, 0)位置,并希望逃到一处不会被袭击到的地方(在第一象限内)。已知每移动一格需要1个时间单位,被流星破坏后的地方不能再进入。给出M个流星在T时刻击中的地方(X, Y),问Bessie能否逃到安全的地方,若能输出最短时间,否则输出-1。分析:依旧是迷宫问题。不同的是,需要自己构建出迷宫。首先将maze的所有格初始化为INF,表示这个格子被袭击的时间为INF(即永远不会被袭击)。对于每一个流星,将其影响反映到maze上,如果破坏范围由重叠,那么格子显示的是较早的破坏时间(因为一旦破坏了就不
阅读全文
摘要:题意:在 H * W 的地图里有 N 个工厂,每个工厂分别生产硬度为1-N 的奶酪,有一只老鼠准备把所有奶酪都吃完。老鼠的初始体力值为1,每吃一个奶酪体力值加 1。已知老鼠不能吃硬度大于当前体力值的奶酪,老鼠只能向上下左右四个方向走,求吃完所有奶酪老鼠需要经过的最小步数。分析:简单迷宫问题。不同的是,老鼠需要按1-N 的顺序把奶酪吃完。用广度优先搜索很容易求出起点到终点的最小步数。初始时,求起点到硬度值为 1 的奶酪的最小步数;接着将起点重置为此位置,继续求此位置到达硬度值为 2 的奶酪;如此类推。因此这里只需做N 次广度优先搜索,并累计其值即可。C++代码: 1 #include 2 #i.
阅读全文
摘要:问题:打冰球。冰球可以往上下左右4个方向走,只有当冰球撞到墙时才会停下来,而墙会消失。当冰球紧贴墙时,不能将冰球往那个方向打。冰球出界就当输,超过10次还没将冰球打到目标位置也当输。求用最小次数将冰球打到目标位置,或输出-1表示输了。分析:一般来说,求最小步数之类的迷宫问题都是用BFS解决的,但这题涉及到迷宫状态的变化(墙),BFS要不断记录状态的变化很复杂,不过网上好像也有人用BFS做的。DFS更加适合这种状态一直变化的,只不过要保存最优值而已,其实最优值也方便剪枝(当前步数已经是当前最优值大小但还没到达目的地也就没必要进行下去了)。需要注意的是,这题并不是移动一格,而是一直移动直到遇到障碍
阅读全文
摘要:题意:按给定顺序从A口放标号位1-10的10个球,利用挡板可以使球落到B或C,问能否使B和C里的球标号从下往上递增。分析:对于第 i 个球,若a[i]大于B口上方的球,则可放入B口;若a[i]大于C口上方的球,则可放入C口。利用深度优先搜索,选取合适的操作,若能按要求放完10个球,则成功。若所有情况都不能,则失败。C++代码:/*input:23 1 4 2 5 6 7 8 9 1010 9 8 7 6 5 4 3 2 1output:YESNO*/#include int a[10];bool dfs(int k, int B, int C){ if(k == 10) return t...
阅读全文
摘要:日文题。。。题意:一个面积为H*W的果园,种了苹果,梨和蜜柑。相邻(上下左右)的果树属于同一个区域,问果园共有多少个区域。分析:迷宫问题。对于每一个格子,可以用深度优先搜索把相同果树的格子遍历并标记。也就是说,每做一次DFS,消灭掉一个区域。只需要遍历果园,对每一个未被标记的格子做DFS,做DFS的次数就是果园的区域数。这里不需要另外用其他数组标记格子已访问,只需要将格子的元素改为一个不会出现的元素如1即可。C++代码: 1 #include 2 #include 3 4 const int MAX_H = 100; 5 const int MAX_W = 100; 6 7 //输入 ...
阅读全文
摘要:题意:有红色和黑色的格子,只能走黑色的,问从起始位置出发,最多能走到达多少块黑色格子。分析:相当于走迷宫,黑色格子是路,红色格子是墙,每次到达一个未到达过的格子时计数,原点也算是一个。每次可以走上下左右四个方向,用深度优先遍历从原点起始,一直到遍历所有能到达的格子。需要注意的是,不要重复走同一个格子,可以采取数组标记已走过的格子,但这里只需简单将已走过的格子标记为红色就可以达到目的,因为红色的格子也不可走。C++代码: 1 #include 2 3 const int MAX_W = 20; 4 const int MAX_H = 20; 5 6 //输入 7 int W; 8 int ...
阅读全文
摘要:描述:某厂根据计划安排,拟将n 台相同的设备分配给m 个车间,各车间获得这种设备后,可以为国家提供盈利Cij(j 台设备提供给i 号车间将得到的利润,1≤i≤m,1≤j≤n) 。问如何分配,才使国家得到最大的盈利?算法基本思路:1.求最大利润输入:c[i][j] = 将 j+1 台设备分配给 i+1 号车间得到的利润。定义:将 j 台设备分配给前 i 个车间的最大利润 p[i][j](即题目所求的是p[m][n]),因此p[i][j]是以下两种情况的较大值:(1)不分配给 i 号车间,此时的最大值为将j 台设备分配给前 i-1 个车间的最大值,p[i][j] = p[i-1][j];(2)分配
阅读全文
摘要:描述:给定一个由n 行数字组成的数字三角形(例如下图)。输出从三角形的顶至底的一条路径,使该路径经过的数字总和最大。(红色路径表示最优路径,结果为9+3+8+7+5 = 32)算法基本思路:显然用一个二维数组rec[0..n-1][0..n-1]可以保存该三角形作为输入(用二维数组对角线以下的位置保存三角形)。对于任意rec[i][j],我们可以定义一个表m[i][j] 来表示以rec[i][j]作为当前路径的终点所得到的最优值。对于m[i][j],要到达这个数字,必须经过前面的某个数字,可以通过计算前面的最优解来构造m[i][j]的最优解。求解m[i][j]的最优解,可以通过子集的最优解构造
阅读全文
摘要:描述:给定总金额为A 的一张纸币,现要兑换成面额分别为a1, a2,…, an 的硬币。硬币兑换问题是用最少枚数的硬币来兑换总金额为A 的纸币。如 a = {1, 2, 5},兑换6元则要2枚硬币(1和5)。根据特定的a,有可能可以直接用贪心算法每次都选取可用的最大硬币值。但对于一些例子,会出现错误情况。如 a = {1, 4, 5},兑换8元。若直接选取最大值,则需要4枚(1个5和3个1),但显然最优值应为2枚(2个4)。对于兑换n元的硬币的最优情况,可以遍历列表 a ,分别选取1个其面值的硬币,再从中挑出最优结果,此时 f(n) = min{f(n-ai)+1}。而每个之前算法的结果都可能
阅读全文
摘要:问题:一个工厂有两条装配线a1, a2,每条装配线有n个装配站,每个编号对等的装配站功能相同。机器只要依次通过编号为1,2,...,n的装配站即可加工完成。已知两条装配线各个装配站装配所需的时间即a1,1,a1,2,...,a1,n, a2,1,a2,2,...,a2,n, 进入装配线所需时间e1,e2,离开装配线所需时间x1,x2。有时候为了加快装配进度,可以将部分完成的机器从一条装配线移到另一条装配线,所需时间分别为t1,1,t1,2,...,t1,n-1, t2,1,t2,2,...,t2,n-1. 求机器制造所需的最短时间。算法基本思路:1.计算最优解即最短时间;要求最短时间,可以看作
阅读全文
摘要:定义:一个包含n个数的序列a0, a1, ... , an-1,求序列的最长非降(>=)子序列及其长度。如:序列5, 3, 4, 9, 6, 8,此最大非降子序列长度为4,子序列为3,4,6,8.(子序列也可能不唯一)运用动态规划,可以构造时间复杂度为O(n2)的算法。算法基本思路:1.打表,获取最长非降子序列的长度;要构造最长非降子序列,可知此序列一定是以序列中某个数作为结尾(好像是废话,但就是那样)。因此,构造表ml[0...n-1],ml[i] 表示前 i 个数以a[i] 为结尾的最长非降子序列的长度。枚举 j (0 ml[i]){ ml[i] =...
阅读全文
摘要:背包问题:n种物品,每种物品有重量w和价值v,背包所能承受的最大重量为c。如何挑选物品可以使总物品的价值最大。0-1背包问题:限定每种物品的个数只能是0或1.如:5个物品,质量分别为3,5,7,8,9,价值分别为4,6,7,9,10。背包所能承受重量为22.给物品从0开始编号,挑选物品1,3,4(价值分别为6,9,10)时,总价值最大为25,此时重量为22.运用动态规划思想,可以构造有效的方法。算法基本思路:1.构造最优表,获取最大价值;构造表mv[0...n][0...c],mv[i][j] 表示 前 i 项物品(即0到i-1)中挑选物品放入承受重量为 j 的最大价值。显然,当 i 为0即没
阅读全文
摘要:定义:设G是一个有向图,其中每条边(i, j)都有一个非负的长度L[i, j],若点i 到点j 没有边相连,则设L[i, j] =∞. 要找出每个顶点到其他所有顶点的最短路径所对应的长度。如:则,L: 0 2 9 8 0 6 1 ∞ 0运用Floyd-Warshall算法,时间复杂度为O(n3),空间复杂度为O(n2).算法基本思路:引理,点 i 到点 j 的最短路径可能是点 i 到点 j 的直接路径长度,也可能是以某点 k 为中间节点,i, k, j 的路径长度。采用自底向上逐步求解的方法,设D[i, j, k] 表示 点 i 到 j 以点集[0..k] 为中间节点的...
阅读全文
摘要:问题:n个矩阵M1M2……Mn链乘法的耗费,取决于n-1个乘法执行的顺序。现在要找到其最小次数的乘法执行顺序。如,n = 4,有以下可能的顺序:(M1(M2(M3M4)))(M1((M2M3)M4))((M1M2)(M3M4))(((M1M2)M3)M4)((M1(M2M3))M4)如果使用暴力算法枚举,时间复杂度为O(2n)。运用动态规划技术,可以将时间复杂度降为O(n3).算法基本思路:1.得到最小乘法次数(1)将矩阵序列在其中找出某个k位置,将其分为两部分;分别求出这两部分的最优解,然后再将其加上这两部分相乘的耗费,就是用当前划分所需要的乘法次数;依次枚举按k划分,比较并取最小乘法次数。
阅读全文

浙公网安备 33010602011771号