算法设计与分析例题分析
文章平均质量分 60
这个专栏是为了保存我在考研期间对《算法设计与分析》一书中例题的学习过程而写。质量并不高,而且不可避免会产生错误,之所以公开发布是希望能与同学分享经验,如有误人子弟的地方可评论指正。
宋瑞梁
本人写的专栏营养价值不高,仅仅是为了记录个人学习过程顺便帮助理解消化,难免出现错误,评论区指正我有空会修改
展开
-
分支限界法——电路板排序问题和批处理作业调度问题
当且仅当到达叶子节点开始结算每条路径的跨越数量,同样还是以当前插槽中包含的电路板数量是否等于其总数量为判断条件,若原创 2022-11-29 00:50:53 · 1663 阅读 · 0 评论 -
分支限界法——最大团问题和旅行售货员问题
其次这个问题需要我们形成回路,那么我们在最后一层也就是n-1层(从0开始,叶子节点为结束点)一定就要和我们的第0层(出发点)的选择是一样的了,也就是说我们无需直接遍历到叶子节点,只需判断n-2层的节点是否能到达叶子节点,如果能就代表是有回路的,否则就直接剪枝。在确定了分支条件和界限之后,我们要选择用堆的形式来判断分支选择,一般以每层来代表一个节点,然后对其进行上界和下界的剪枝,其中界限也是会动态变化的,因此也要用算法来确定动态变化的界限,最后当到达叶子节点则得到我们的答案。原创 2022-11-26 00:33:06 · 2535 阅读 · 0 评论 -
分支限界法——布线问题和01背包问题
我们观察题目不难发现,其实两点之间的最短路径(在没有封锁的情况下),其在水平方向运动的格子数相当于二者的横坐标之差的绝对值,而在垂直方向运动的格子数相当于二者的纵坐标之差的绝对值。那么我们知道优先队列关键在于优先,我们要定义路径选择的优先级,也就是说对于物品的选择要有优先度,那么性价比就成为我们考虑优先度的第一选择,因此我们每层的选择以性价比为依据建立优先队列,图上的标距离是有问题的,每格需要加1,到达b时标距离是9,实际距离就是9-2+2=7,而ab间的距离是7+2=9(路径长+ab两格)。原创 2022-11-23 00:16:41 · 1442 阅读 · 0 评论 -
分支限界法——装载问题
在图中所给的例子中我们发现,up=所有选中的货物重量+可供选择的货物重量,它所代表的是最大重量的上界,那么如果我们要寻找最优解,肯定要从上界大的子树里寻找。而优先队列实际上表达的是对界限的动态更新,每层的上界或者下界都是实时更新着的,我们每次所遍历的最优解都可以作为新的上界或下界,这样做的好处是将一部分的路径可以直接剪枝,使得计算量更少。分支限界法的概念是分支和限界,分支即我们如何选取拓展节点,限界即我们需要限定的上界和下界。比如如果我们的解达到了上界,说明已经是最优了,那么就是我们所求的解。原创 2022-11-22 00:26:47 · 4065 阅读 · 0 评论 -
分支限界法——以单源最短路径为例,理解什么是分支限界法
这个子树是怎么得到的呢,首先在图1中我们可以看到a到bcd都有路径,在树中每个结点旁边的数字即为它的下界,比如b的下界是3=1+2,即入度+最小出度。对应的,c是7,d是11。接下来按广度优先遍历第三层,同理我们发现abc这条路径上,c的下界是6,而ac路径上c的下界是7,也就是说abc优于ac,因此我们舍弃了ac的子树不再遍历。而我们对于重复遍历的结点,仅仅保留最短路径的子树,即aeq和bg两个,其他的都剪枝,其余顶点也是同理。然后在这个堆中,s到b的路长是3,是现在最小的,因此遍历3的子节点gf。原创 2022-11-18 00:12:43 · 3569 阅读 · 0 评论 -
算法设计与分析第五章——回溯法课后习题
另外在展示答案代码之前我还有一种想法,我们以每行为一层深度,因为如果某形状某颜色被某格[i][j]选取之后,那么整个i行j列都不能有该形状和该颜色,我们不妨每行的n格看作n次循环,每次我们选取后cc[a[i][j]][b[i][j]]=1,比如现在是cc[1][1]=1,也就是第1行第1格为1。假设男1配女2,即P[1][2]*Q[2][1]不一定是最大的,因为P[1][2]和P[2][1]是不一样的,因此我们还需要交换次序比较P[2][1]*Q[1][2]的大小。既然要遍历矩阵,那么最好是逐行遍历。原创 2022-11-14 23:00:07 · 1151 阅读 · 0 评论 -
回溯法——圆排序问题,电路板问题
total[j]这里,如果当前面的i个插槽中已经用去了连接块j中的所有电路板,那么就是说剩下的插槽不可能再有连接块j的电路板了,也就不可能再被跨越!其次找到剪枝条件,这个题目中要求圆和矩阵的底边是相切的,这一点就要求矩形的长m=序列中第一个圆形的半径+接下来每两个圆形的半径连线构成的三角形边长+最后一个圆形的半径。先看now[j]>0,(now[j]表示的是x[1:i]中所包含的Nj的电路板数),now[j]大于零表示前面的i个插槽中有连接块j的电路板存在,很好理解.我也没看懂,找了个更详细的博客。原创 2022-11-06 00:45:20 · 686 阅读 · 0 评论 -
回溯法——图的m着色问题和旅行售货员问题
首先我们确定是排序树问题,输入给出了这是一个m着色的n结点图,也就是给出了结果,那么让我们用回溯法去寻找其解空间,既然有m着色,就代表这是一个完全m叉树,每个结点下面有m种颜色分配方法(还未剪枝),当然我们要根据题示,将同一条边上两个颜色相同顶点,也就是在树上父节点和子节点分配颜色相同的子树要剪枝。题目没详细说明旅行售货员问题,问题如下:某售货员要到若干个城市推销商品,已知各城市之间的路程(或旅费),他要选定一条从驻地出发,经过每个城市一遍最后回到驻地的路线,使总的路线(或总的旅费)最小。原创 2022-11-04 00:22:49 · 440 阅读 · 0 评论 -
回溯法——01背包问题和最大团问题
题目还给出一种思想,为了方便计算上界(即cp+r>当前bestp的最大值情况),我们可以将这个解空间树的结点按照单位价值(性价比)从大到小进行排序,这样每深入一层,我们每次加入的总是最大性价比的物品,因为我们优先加入性价比高的,这样算出来的解一定是最优的,也尽可能的减少了遍历长度,省去了其他多余的剪枝步骤。那么在根据题目要求,一个图的团需要满足它是一个完全子图,并且不被更大的完全子图包含。然后需要我们求出这个图G的最大团,如果像如图给出的例子有三种最大团,也就是说最大团也不唯一。原创 2022-11-01 23:14:29 · 665 阅读 · 0 评论 -
回溯法——符号三角形,n后问题
总符号数=(1+n)n/2,并且+和-符号相同,则+和-分别有(1+n)n/4个,那么这个n*(n+1)还需要可被4整除作为三角形存在的判断条件,因此我们可以给题目加上判断条件,任一符号都不能超过(1+n)n/4个,否则剪枝。用x[n][m]代表棋盘第n行m列,若x[i][j]有皇后,那么第i行不能有其他皇后,第j列也不能有,同时x[i+t][j+t] 也不能有(t>=1),若第二个皇后放在x[k][L],那么就有k!因此我们决定在层数上由上到下进行回溯,只需决定第一行就可以知道下面所有的符号。原创 2022-10-31 23:03:14 · 722 阅读 · 0 评论 -
回溯法——装载问题和批处理作业调度
通常是因为当前的结果已经不符合我们的判断条件了(还记得上一节讲到回溯法的算法里总要加上判断条件吗,一个答案的解一定符合我们的条件,不符合的就需要剪枝),如果当前的结果已经不符合我们的条件,比如这题中已经超载了,那么其子树——就相当于再加一个箱子到船上,必然也是超载的,那么从超载开始的这一个结点以及以下的各个子结点必然都不符合我们的解的需求,因此我们就对这个结点进行剪枝,就省去了遍历那些错误结果的时间。其类似于一个01背包问题。更好的最优解优化可以采用之前学习过的动态规划的思想,最优结构的子结构也应当最优。原创 2022-10-31 00:40:26 · 360 阅读 · 0 评论 -
回溯法——回溯法的算法思想
观察代码可以发现搜索排序树的回溯法就多了个Swap函数来排序结果,比如123是以1为分支的一个结果,遍历了123,132后,下一个有规律的结果就是将第一位的1和后面两位互换,也就是213与231,同理将第一位的1和3互换就是321和312。简单来说,回溯法是一个在所有可能性中寻找最优解的问题,但与遍历所有路径的全遍历不同的是:回溯法可能在中间的某一步产生了分支,我们在遍历路径的时候,可以选择从原来选择后的路径倒退回那个分叉路口,选择其他的分支。Backtrack(t)中的t代表的就是树的深度(层次)。原创 2022-10-30 00:08:05 · 587 阅读 · 0 评论 -
算法设计与分析第四章——贪心算法课后习题
假设n可以拆分成a+b,要求ab最大值,n2=a2+2ab+b2,n2-(a2+b2)=2ab,两边同时加上2ab得n2-(a2-2ab+b2)=n2-(a-b)2=4ab,n不变,a-b的绝对值越小,ab越小,反之 a-b的绝对值越大,ab越大。例题用贪心算法,从2开始依次从n中拆出自然数,使得乘积尽可能大,a[k]数组代表第几个因数,其值代表这个因数的数值,直到n原创 2022-10-27 23:27:04 · 834 阅读 · 0 评论 -
算法设计与分析第四章——贪心算法分析题
很多时候贪心算法并不能给出最优解,我们可以这样思考,要使得时间最短,比如我先分配给1,接下来该分配给2了,但是1的时间还是短于2的时间,如果分配给2肯定没有分配给1之后的时间短。题目所给的A-H如图所示,易得规律,叶子节点上的数字是斐波那契数列,二叉树总共有n层(算上根节点),正好对应前n个斐波那契数 ,第二层叶子节点对应第8个,第三层叶子对应第七个,依次类推,第t+2层结点对应第n-t个斐波那契数(n-2>t>=0)。哈夫曼树就是最优编码树,不过本题中要求用前缀码的序列,也就是根左右的顺序。原创 2022-10-17 23:57:48 · 315 阅读 · 0 评论 -
贪心算法——最小生成树
Prim算法的原理是从最小权值边开始,每次从上一个顶点集合的相邻边中找最短的权值边,再把新加入的顶点视作新集合。Kruskal算法则孤立各个顶点,每次只选取其中的最短路径,使得每次不同连通分支的集合数量越来越少,最后集合数量只剩一个则完成生成树。经典算法是Prim算法和Kruskal算法,他们都是基于贪心算法的。1.因为是选取最短路径,那么每次选取路径应当确认这条路径上的两个顶点是不是属于不同联通分支,只有当两个顶点属于不同连通分支才可选取该路径,否则同一连通分支的路径无法选择。原创 2022-10-16 00:34:53 · 2292 阅读 · 0 评论 -
贪心算法——哈夫曼编码与Dijkstra算法
比如第一轮,我们发现初始dist中dist[2]最小,说明点1到点2最短,因此我们第一轮选择路径为V1V2,集合{1,2}那么保持dist[2]不变(排除已选节点的dist),V2的前一个结点prev[2]=1。所以最终的最短路径是V1435。迪杰斯特拉算法是一个贪心算法求单源最短路径的经典问题,核心思想是在原有向图中,V1V2之间的权值可以记作c[1][2],若两点连通则c[1][2]中保存其路径长,否则c[1][2]=+∞。(为了防止解码时对编码的误判,权值只会放在叶子结点。原创 2022-10-15 00:04:49 · 415 阅读 · 0 评论 -
算法设计与分析第三章——动态规划课后题算法题
即减少最后一个作业的时间,p(i-ak,j,k-1)代表A不处理这个作业,但B的用时仍然相同,p(i,j-bk,k-1)代表B不处理这个作业,但A的用时仍然相同。这种题目只能遍历来查找,如果我们将7视作a[1][1],5视作a[5][2],用m[5][2]代表a[5][2]到a[1][1]的最大路径,那么m[5][2]的途径最大路径中一定有max{m[4][1],m[4][2]}即两条分支路径到a[1][1]也应是最大长度,因此就成为一个最优子结构的问题。而非A处理2作业,B处理1作业 ,时间为8。原创 2022-10-10 23:47:04 · 677 阅读 · 0 评论 -
动态规划——最优二叉搜索树
此外还有改进算法,在已知s存储最优子结构的根节点的情况下,用i1,j1区分[i][j]的左右子树期望代价数组m[i][i1],m[j1][j],其中当s[i][j-1]>i,说明i一定在s[i][j-1]的左子树内那么求m[i][j]的期望代价实际就是求左右区间m【i】【s[i][j-1]】和m【i】【s[i+1][j]】的期望代价之和,直接使得i1=s[i][j-1],反之i1=i,j1亦然。如果我们查找的总体期望代价是最低的,就代表这是最优查找。总体期望代价=每层期望代价之和(最优子结构思想)原创 2022-10-08 00:26:38 · 6156 阅读 · 0 评论 -
动态规划——01背包问题
m(i,j)代表从i开始到n的当前背包余量为j的01背包问题的最优解。若余量可装下Wi,那么比较装下Wi即m(i+1,j-Wi)+Vi和不装下Wi即m(i+1,j)哪个价值更大,哪个即为最优子结构。比如一个背包容量为11,按顺序=6+3+1,那么最后一步+1一定是在6+3的基础上,背包余量=11-6-3=2时寻找的最优解。同理3是在6的基础上找到的最优解,那么此时余量是11-6=5。一个经典的动态规划的问题,对于每个物品,只有装或者不装两种选项,我们需要让背包装的价值尽可能高,并且不超过总重量C。原创 2022-10-04 23:56:13 · 474 阅读 · 0 评论 -
动态规划法——凸多边形最优三角划分
再看上图b的图形,假如要在这个图形中得到最优子结构,即权值和最小,那么如果把这个n边形分成两个子多边形+一个三角形,那么这两个子多边形各自所划分的结构也应当是最优子结构,因为整体最优那么部分一定也是最优,否则如果部分有更优结构,整体就不会是最优结构。t[i][k]代表Vi-1~Vk的图形,t[k+1][j]代表Vk~Vj的图形,w(Vi-1VkVj)代表它们分出的三角形,三者之和正好为我们所求的划分权值之和,遍历所有分割方式取其中最小值即为最优值。原创 2022-10-03 00:12:09 · 954 阅读 · 0 评论 -
动态规划——最长公共子序列
比如X总共8位,Y总共5位,那么当j=5,j再增长也没有意义了,比如C[6][6]=C[6][5],不可能比C[5][5](即C[5][6],二者同样)要更小,因此C[6][6]=max{C[6][5],C[5][6]},C[i+1][j+1]=max{C[i+1][j],C[i][j+1]}化为C[i][j]=max{C[i][j-1],C[i-1][j]}=Yi,C[i+1][j+1]=max{C[i+1][j],C[i][j+1]}化为C[i][j]=max{C[i][j-1],C[i-1][j]}原创 2022-09-30 22:52:19 · 504 阅读 · 0 评论 -
分治法——棋盘覆盖
和第一题同样的道理,首先这个算法将每个大矩阵分为11到22四个小矩阵,类似于拉普拉斯行列式的运用,然后将原来本来是矩阵乘积之和的C矩阵用操作M的加减来表示,而操作M中包含了7次乘法运算,比直接用AB乘积表示C矩阵的8次乘法运算少一次。int t=tile++,tile是公共变量,因此只要我们分治一次,tile就加一次,而后面的代码其实表明了,我们每完成一趟分治都要放一个L型骨牌,说明tile其实就代表当前放的骨牌序号,代表我们放的是第几个骨牌。通过减少乘法的运算次数,降低运算复杂度。原创 2022-09-19 22:01:00 · 766 阅读 · 0 评论 -
动态规划——矩阵连乘问题
那么我们列出计算m[i][j]的矩阵,其中m[i][j]是计算了Ai*Aj,比如m[1][2]就是A1*A2=15750,m[2][3]就是A2*A3=2625,而m[1][3]则是A1*A2*A3,即A1*(A2*A3)+m[2][3],而m[2][4]是(A2*A3)*A4。也就是说,m[i][j]代表了从Ai*...Aj的矩阵连乘的最小值,而。例如,计算三个矩阵连乘{A1,A2,A3};由于矩阵乘法满足结合律,故计算矩阵的连乘积可以有许多不同的计算次序。这种计算次序可以用加括号的方式来确定。原创 2022-09-29 23:36:50 · 585 阅读 · 0 评论 -
递归算法之整数划分问题
递归算法之整数划分问题原创 2022-09-18 21:43:23 · 1522 阅读 · 0 评论 -
递归算法——汉诺塔
递归算法——汉诺塔原创 2022-09-18 22:26:47 · 350 阅读 · 0 评论 -
分治法——线性时间选择
j=i-p+1即为[p,i]中包含的元素,虽然还未对这两段进行过排序,但我们知道左端是小于a[j]的,而右端是大于a[j]的,因此a[j]的排序顺序是正确的,我们比较k与j的大小,如果发现kj时,则对右端进行随机选取。从中位数组的中位数划分出k的位置,然后寻找到k应当属于那一个中位数组,最后在这个中位数组中寻找k的位置。原创 2022-09-22 22:22:51 · 406 阅读 · 0 评论 -
分治法——合并排序
该写的字都写在图片里了。原创 2022-09-20 23:52:27 · 140 阅读 · 0 评论 -
算法设计与分析第二章——递归与分治法课后题分析题
因此我们的1经历了(a,c,b) ——(c,b,a)——(b,a,c)——(a,c,b)我们发现构成了一个循环,而这个循环正是所有圆盘在汉诺塔的移动中都会遵守的规律,直到最后一个圆盘1从(a,c,b) ——(c,b,a),此时全部圆盘就移动到了b上,因此我们认为汉诺塔的递归和非递归本质上的一回事。反之若x>=a[mid],则将L=mid,如果x=a[L]那就是已经找到了,L也无需移动,如果x>a[L]则移动L,随着mid的来回移动,反正x是在L的右边,mid迟早找到x的位置并保存在L。考研不大可能考到吧。原创 2022-09-25 23:06:45 · 368 阅读 · 0 评论 -
分治法——循环赛日程表
假设k=2,n进入循环n/2=2,t循环两次,然后m*2=2,下次进来i循环2次,m*2*2=8,完全错了。总共2^k个选手,正好为2的整数幂,每位选手每天只能比一次,必须与其他选手各比赛一次,总共n-1天。不难发现,图中左上角的红框部分和右下角红框部分相同,左下角蓝框和右上角蓝框部分相同,也就是说我们只需要从一半对称到另一半就可以完成这个矩阵。这样求不是简单很多吗,求出左上右上,然后对称一下,非得搞得那么麻烦,浪费时间。左下方矩阵=右上方矩阵对称,右下方矩阵=左上方矩阵对称。原创 2022-09-24 00:40:41 · 4657 阅读 · 6 评论 -
Perm递归排列问题
总的来说,其思想就是以k为开始,m为结束,前0~(k-1)位作为前缀,主要处理后k~m位,然后从k+1位开始,与后面剩余位数依次交换,交换一次输出一次。先是11交换22交换23交换33输出,然后12交换22交换23交换33输出,再13交换22交换23交换33输出。关于算法设计与分析中的2-4是 有疑问的,原文的代码注释不完善,而这个链接的代码显然更方便理解。后三位记录为123,原创 2022-09-17 21:50:03 · 236 阅读 · 0 评论 -
分治法——快速排序
书上还介绍了一种随机从数组中选择一个数字作为基准的快速排序算法,其实就是生成随机数i,然后交换a[i],a[p]的位置,就变成了 a[i]在首部了,本质上还是以每组第一个元素为基准的快速排序,不过随机选取的基准使得期望更加对称。快速排序都是以每段数组的第一个元素p作为基准的。快速排序是一种基于分治法的排序算法,简单来说。原创 2022-09-21 22:24:05 · 1644 阅读 · 0 评论