目录第二章递归与分治 (3)1、用递归思想求N! (3)2、用递归思想求Fibonacci数列 (3)3、用递归思想求排列问题 (4)4、用递归思想求整数划分问题 (5)5、用递归思想求汉诺塔问题 (6)6、用递归思想实现插入排序 (7)7、用分治思想实现二分查找 (8)8、用分治法求两个大整数的乘法 (9)9、用分治思想求一个数组的最大值与最小值 (10)10、用分法思想实现合并排序 (12)11、用分治思想实现快速排序 (13)12、用分治法实现线性时间选择问题 (15)13、用分法思想实现残缺棋盘问题 (15)第三章动态规划法 (18)1、矩阵连乘问题 (18)2、最长公子序列 (20)3、最大子段和问题 (23)4、图像压缩问题 (28)5、电路布线问题 (31)6、最 (31)7、最 (31)第四章贪心算法 (32)1、哈夫曼编码 (32)4、Kruskal算法求最小生成树 (35)5、集装箱问题 (38)6、活动安排问题 (40)第五章回溯法 (42)1、用回溯法求0-1背包问题 (42)2、用回溯法求N皇后问题 (45)3、用回溯法求旅行售货员问题 (46)4、用回溯法求圆排列问题 (48)5、用回溯法求符号三角形问题 (50)6、用回溯法求批处理作业调度问题 (52)7、用回溯法求连续邮资问题 (54)8、用回溯法求图的m着色问题 (57)9、用回溯法求最大团问题 (59)第六章回溯法 (62)1、用分支限界法求0-1背包问题 (62)第二章递归与分治1、用递归思想求N!王晓东版——《计算机算法设计与分析(第四版)》P11页,例2-12、用递归思想求Fibonacci数列王晓东版——《计算机算法设计与分析(第四版)》P12页,例2-23、用递归思想求排列问题王晓东版——《计算机算法设计与分析(第四版)》P13页,例2-4N个元素的全排列的个数为:N!本算法非常重要,因为它是很多算法的基础,比如回溯法那章里的算法很多都是以本算法为基础的。
4、用递归思想求整数划分问题王晓东版——《计算机算法设计与分析(第四版)》P14页,例2-5整数划分问题是算法中的一个经典命题之一,有关这个问题的讲述在讲解到递归时基本都将涉及。
所谓整数划分,是指把一个正整数n写成如下形式:n=m1+m2+……+mi; (其中mi为正整数,并且1 <= mi <= n),则{m1,m2,...,mi}为n的一个划分。
如果{m1,m2,...,mi}中的最大值不超过m,即max(m1,m2,...,mi)<=m,则称它属于n的一个m划分。
这里我们记n的m划分的个数为f(n,m);例如,但n=4时,他有5个划分,{4},{3,1},{2,2},{2,1,1},{1,1,1,1};注意4=1+3 和4=3+1被认为是同一个划分。
该问题是求出n的所有划分个数,即f(n, n)。
下面我们考虑求f(n,m)的方法;根据n和m的关系,考虑以下几种情况:(1) 当n=1 时,不论m的值为多少(m>0),只有一种划分即{1};(2) 当m=1 时,不论n的值为多少,只有一种划分即n个1,{1,1, 1, ..., 1 };(3) 当n=m 时,根据划分中是否包含n,可以分为两种情况:(a). 划分中包含n的情况,只有一个即{ n };(b). 划分中不包含n的情况,这时划分中最大的数字也一定比n 小,即n 的所有( n - 1 ) 划分。
因此f(n, n) = 1 + f(n, n-1);(4) 当n < m 时,由于划分中不可能出现负数,因此就相当于f(n, n);(5) 但n > m 时,根据划分中是否包含最大值m,可以分为两种情况:(a). 划分中包含m的情况,即{m,{x1,x2, ...,xi}},其中{x1,x2, ...,xi }的和为n-m,可能再次出现m,因此是(n-m)的m划分,因此这种划分个数为f(n-m, m);(b). 划分中不包含m的情况,则划分中所有值都比m小,即n的(m-1)划分个数为f(n, m - 1);因此f(n, m) = f(n-m, m) + f(n, m-1);综合以上情况,我们可以看出,上面的结论具有递归定义特征,其中(1)和(2)属于回归条件,(3)和(4)属于特殊情况,将会转换为情况(5)。
而情况(5)为通用情况,属于递推的方法,其本质主要是通过减小m以达到回归条件,从而解决问题。
其递推表达式f(n, m) = 1; ( n = 1 or m = 1 )f(n, m) = f(n, n); ( n < m )f(n, m) = 1+ f(n, m - 1); ( n = m )f(n, m) = f(n - m, m) + f(n, m - 1); ( n > m )因此我们可以给出求出f(n, m) 的递归函数代码如下。
怎样求出具体的划分结果呢?这个问题比较难解决,等进一步分析。
5、用递归思想求汉诺塔问题6、用递归思想实现插入排序#include <stdio.h>#include <stdlib.h>#include <time.h>void insertSort(int *aa,int n){if(n>0){n = n-1;insertSort(aa,n);int a= aa[n];int k = n-1;while((k>=0)&& a<aa[k]){aa[k+1] = aa[k];k--;}aa[k+1] = a;}}void main(){int a[10];srand((unsigned int)time(NULL));for(int i=0;i<10;i++){a[i] = rand()%100;printf("%d ",a[i]);}printf("\n");insertSort(a,10);for(i=0;i<10;i++)printf("%d ",a[i]);printf("\n");}7、用分治思想实现二分查找8、用分治法求两个大整数的乘法最简单的方法,这里没有体现分治法的思想9、用分治思想求一个数组的最大值与最小值10、用分法思想实现合并排序11、用分治思想实现快速排序如果每次划分不以a[p]为基准,而是随机从a[p]-a[r]里取一个数为基准,则可以设计如下随12、用分治法实现线性时间选择问题本算法要用到上面快速排序的随机划分算法13、用分法思想实现残缺棋盘问题王晓东版——《计算机算法设计与分析(第四版)》P20页,例2.6注意:同一种形状的骨牌,在填充时数字不一样,关键看三个相同数字摆放位置所构成的形状。
第三章动态规划法1、矩阵连乘问题2、最长公子序列3、最大子段和问题(1)分治思路实现(2)动态规划思路实现补充了书本上不完美的地方:在求最大子段和,随便可以求出最大子段和的起始坐标和终止坐标;在求最大子矩阵和时,可以随便求出子矩阵的左上角和右下角坐标。
4、图像压缩问题王晓东版——《计算机算法设计与分析(第四版)》P65页,例3.7书本上P67页上第一行b[j] = b[s[j]]行错误,本程序修正了这个错误,在求每段的最大位数时,只需要从头到位扫描一次,时间复杂度为O(n)。
小有成就感^_^5、电路布线问题6、最7、最第四章贪心算法1、哈夫曼编码4、Kruskal算法求最小生成树设有如下无向图,求这个图的最小生成树。
判断两个节点是否连通,用并查集结构来实现。
5、集装箱问题6、活动安排问题第五章回溯法回溯法的基本步骤(1)针对所给问题,定义问题的解空间;(2)确定易于搜索的解空间结构;(3)以深度优先方式搜索解空间,并在搜索过程中用剪枝函数避免无效搜索。
回溯法的基本思想在搜索的过程中动态产生问题的解空间。
在任何时刻,算法只保存从根结点到当前扩展结点的路径,这可以节省大量的空间,如果将有的路径全部保存下来,将需要一个巨大的空间。
迭代回溯的算法基本框架(没有理解)void IterativeBacktrack(void){int t = 1;while(t>0){if( f(n,t) <= g(n,t)){for(int i= f(n,t);i<=g(n,t);i++){x[t] = h(i);if(Constraint(t) && Bound(t)){if(Solution(t))Output(x);elset++; // 向纵深方向搜索}}//end for}elset--;}}1、用回溯法求0-1背包问题0-1背包问题的解空间是一棵子集树2、用回溯法求N皇后问题问题描述:在一个N*N棋盘上,放置N个皇后,它们不能在同一行,同一列,以及同一斜线上。
3、用回溯法求旅行售货员问题问题描述:某售货员要到若干城市去推销商品,已知各城市之间的路程(或费用),他要选择一条从驻地出发,经过每个城市一遍,最后回到驻地的路线,使总的路程最短。
4、用回溯法求圆排列问题(1)问题描述给定n个大小不等的圆,将它们排在一个水平面上,求总水平长度最短的圆排列方式。
例如有3个半径分别1,1,2的圆,第一种排列方式为:前面放两个半径为1的小圆,后面跟一个半径为2的大圆,这种排列方式所占的总水平长度为5+2*sqrt(2)。
第二种排列方式为:半径为大圆放中间,两个小圆分别在两侧,这种排列方式所占的总长度为2+4*sqrt(2)。
所以对于同一组圆,不同的排列方式,得到的总水平长度是不一样的。