《动态规划入门》PPT课件.ppt

上传人:牧羊曲112 文档编号:5472796 上传时间:2023-07-11 格式:PPT 页数:69 大小:529KB
返回 下载 相关 举报
《动态规划入门》PPT课件.ppt_第1页
第1页 / 共69页
《动态规划入门》PPT课件.ppt_第2页
第2页 / 共69页
《动态规划入门》PPT课件.ppt_第3页
第3页 / 共69页
《动态规划入门》PPT课件.ppt_第4页
第4页 / 共69页
《动态规划入门》PPT课件.ppt_第5页
第5页 / 共69页
点击查看更多>>
资源描述

《《动态规划入门》PPT课件.ppt》由会员分享,可在线阅读,更多相关《《动态规划入门》PPT课件.ppt(69页珍藏版)》请在三一办公上搜索。

1、,动态规划入门晋江市养正中学 张昱峥,三角形的行数大于1小于等于100,数字为 0-99,例题一、数字三角形7,3,8,8 1 02 7 4 44 5 2 6 5在上面的数字三角形中寻找一条从顶部到底边的路径,使得路径上所经过的数字之和最大。路径上的每一步都只能往左下或右下走。只需要求出这个最大和即可,不必给出具体路径。,输入格式:,5,/三角形行数。下面是三角形,73 88 1 02 7 4 44 5 2 6 5要求输出最大和,解题思路:用二维数组存放数字三角形。D(r,j):第r行第 j 个数字(r,j从1开始算)MaxSum(r,j):从D(r,j)到底边的各条路径中,最佳路径的数字之和

2、。问题:求 MaxSum(1,1)典型的递归问题。D(r,j)出发,下一步只能走D(r+1,j)或者D(r+1,j+1)。故对于N行的三角形:if(r=N)MaxSum(r,j)=D(r,j)elseMaxSum(r,j)=Max MaxSum(r1,j),MaxSum(r+1,j+1),+D(r,j),int DMAXMAX;int n;int MaxSum(int i,int j)if(i=n),return Dij;int x=MaxSum(i+1,j);int y=MaxSum(i+1,j+1);return max(x,y)+Dij;,数字三角形的递归程序:#include#incl

3、ude#define MAX 101using namespace std;,int main()int i,j;cin n;for(i=1;i=n;i+),for(j=1;j Dij;cout MaxSum(1,1)endl;,回答:重复计算,为什么超时?7131 81,01,8121,1273,43,41,41,54,26,64,51,如果采用递规的方法,深度遍历每条路径,存在大量重复计算。则时间复杂度为 2n,对于 n=100行,肯定超时。,如果每算出一个MaxSum(r,j)就保存起来,下次用到其值的时候直接取用,则可免去重复计算。那么可以用O(n2)时间完成计算。因为三角形的数字总数

4、是 n(n+1)/2,改进,数字三角形的记忆递归型动归程序:#include#include using namespace std;#define MAX 101int DMAXMAX;int n;int maxSumMAXMAX;,int MaxSum(int i,int j)if(maxSumij!=-1)return maxSumij;if(i=n)maxSumij=Dij;else int x=MaxSum(i+1,j);int y=MaxSum(i+1,j+1);,maxSumij=max(x,y)+Dij;return maxSumij;,int main()int i,j;ci

5、n n;for(i=1;i Dij;maxSumij=-1;,cout MaxSum(1,1)endl;,递归转成递推,7,3 8,8 1 0,2 7 4 4,4 5 2 6 5,递归转成递推,7,3 8,8 1 0,2 7 4 4,4 5 2 6 5,递归转成递推,7,3 8,8 1 0,2 7 4 4,4 5 2 6 5,递归转成递推,7,3 8,8 1 0,2 7 4 4,4 5 2 6 5,递归转成递推,7,3 8,8 1 0,2 7 4 4,4 5 2 6 5,递归转成递推,7,3 8,8 1 0,2 7 4 4,4 5 2 6 5,递归转成递推,7,3 8,8 1 0,2 7 4

6、4,4 5 2 6 5,递归转成递推,7,3 8,8 1 0,2 7 4 4,4 5 2 6 5,递归转成递推,#include#include using namespace std;#define MAX 101int DMAXMAX;int n;int maxSumMAXMAX;int main()int i,j;cin n;for(i=1;i Dij;for(int i=1;i=n;+i)maxSumni=Dni;,for(int i=n-1;i=1;,-i),for(int j=1;j=i;+j)maxSumij=max(maxSumi+1j,maxSumi+1j+1)+Dijcou

7、t maxSum11 endl;,4,空间优化73 88 1 02 7 4 4,4 5 2 6 5,5,2,6,5,没必要用二维maxSum数组存储每一个MaxSum(r,j),只要从底层一行行向上递推,那么只要一维数组maxSum100即可,即只要存储一行的MaxSum值就可以。,7,空间优化73 88 1 02 7 4 4,4 5 2 6 5,5,2,6,5,没必要用二维maxSum数组存储每一个MaxSum(r,j),只要从底层一行行向上递推,那么只要一维数组maxSum100即可,即只要存储一行的MaxSum值就可以。,7,空间优化73 88 1 02 7 4 4,4 5 2 6 5,

8、12,2,6,5,没必要用二维maxSum数组存储每一个MaxSum(r,j),只要从底层一行行向上递推,那么只要一维数组maxSum100即可,即只要存储一行的MaxSum值就可以。,7,空间优化73 88 1 02 7 4 4,4 5 2 6 5,12,10,6,5,没必要用二维maxSum数组存储每一个MaxSum(r,j),只要从底层一行行向上递推,那么只要一维数组maxSum100即可,即只要存储一行的MaxSum值就可以。,7,空间优化73 88 1 02 7 4 4,4 5 2 6 5,12,10,10,5,没必要用二维maxSum数组存储每一个MaxSum(r,j),只要从底层

9、一行行向上递推,那么只要一维数组maxSum100即可,即只要存储一行的MaxSum值就可以。,20,空间优化73 88 1 02 7 4 4,4 5 2 6 5,12,10,10,5,没必要用二维maxSum数组存储每一个MaxSum(r,j),只要从底层一行行向上递推,那么只要一维数组maxSum100即可,即只要存储一行的MaxSum值就可以。,20,空间优化73 88 1 02 7 4 4,4 5 2 6 5,13,10,10,5,没必要用二维maxSum数组存储每一个MaxSum(r,j),只要从底层一行行向上递推,那么只要一维数组maxSum100即可,即只要存储一行的MaxSum

10、值就可以。,递归到动规的一般转化方法,递归函数有n个参数,就定义一个n维的数组,数组的下标是递归函数参数的取值范围,数组元素的值是递归函数的返回值,这样就可以从边界值开始,逐步填充数组,相当于计算递归函数值的逆过程。,动规解题的一般思路1.将原问题分解为子问题,把原问题分解为若干个子问题,子问题和原问题形式相同或类似,只不过规模变小了。子问题都解决,原问题即解决(数字三角形例)。子问题的解一旦求出就会被保存,所以每个子问题只需求解一次。,动规解题的一般思路2.确定状态,在用动态规划解题时,我们往往将和子问题相关的各个变量的一组取值,称之为一个“状态”。一个“状态”对应于一个或多个子问题,所谓某

11、个“状态”下的“值”,就是这个“状态”所对应的子问题的解。,动规解题的一般思路,2.确定状态,所有“状态”的集合,构成问题的“状态空间”。“状态,空间”的大小,与用动态规划解决问题的时间复杂度直接相关。在数字三角形的例子里,一共有N(N+1)/2个数字,所以这个问题的状态空间里一共就有N(N+1)/2个状态。,整个问题的时间复杂度是状态数目乘以计算每个状态所需,时间。,在数字三角形里每个“状态”只需要经过一次,且在每个,状态上作计算所花的时间都是和N无关的常数。,动规解题的一般思路,2.确定状态,用动态规划解题,经常碰到的情况是,K个整型变量能构成一个状态(如数字三角形中的行号和列号这两个变量

12、构成“状态”)。如果这K个整型变量的取值范围分别是N1,N2,Nk,那么,我们就可以用一个K维的数组arrayN1 N2Nk来存储各个状态的“值”。这个,“值”未必就是一个整数或浮点数,可能是需要一个结构才能表示的,那么array就可以是一个结构数组。一个“状态”下的“值”通常会是一个或多个子问题的解。,动规解题的一般思路,3.确定一些初始状态(边界状态)的值,以“数字三角形”为例,初始状态就是底边数字,值,就是底边数字值。,动规解题的一般思路,4.确定状态转移方程,定义出什么是“状态”,以及在该“状态”下的“值”后,就要,找出不同的状态之间如何迁移即如何从一个或多个“值”已知的“状态”,求出

13、另一个“状态”的“值”(“人人为我”递推型)。状态的迁移可以用递推公式表示,此递推公式也可被称作“状态转移方程”。,数字三角形的状态转移方程:,能用动规解决的问题的特点,1)2),问题具有最优子结构性质。如果问题的最优解所包含的子问题的解也是最优的,我们就称该问题具有最优子结构性质。无后效性。当前的若干个状态值一旦确定,则此后过程的演变就只和这若干个状态的值有关,和之前是采取哪种手段或经过哪条路径演变到当前的这若干个状态,没有关系。,例题二:最长上升子序列,问题描述,一个数的序列ai,当a1 a2.aS的时候,我们称这个序列是上升的。对于给定的一个序列(a1,a2,.,aN),我们可以得到一些

14、上升的子序列(ai1,ai2,.,aiK),这里1=i1,i2.iK=N。比如,对于序列(1,7,3,5,9,4,8),有它的一些上升子序列,如(1,7),(3,4,8)等等。这些子序列中最长的长度是4,比如子序列(1,3,5,8).,你的任务,就是对于给定的序列,求出最长上升子序列的长度。,输入数据,输入的第一行是序列的长度N(1=N=1000)。第二行给出,序列中的N个整数,这些整数的取值范围都在0到10000。,输出要求,最长上升子序列的长度。输入样例7,1 7 3 5 9 4 8输出样例4,解题思路,1.找子问题,“求序列的前n个元素的最长上升子序列的长度”是个子问题,但这样分解子问题

15、,不具有“无后效性”假设F(n)=x,但可能有多个序列满足F(n)=x。有的,序列的最后一个元素比 an+1小,则加上an+1就能形成更长上升子序列;有的序列最后一个元素不比an+1小以后的事,情受如何达到状态n的影响,不符合“无后效性”,解题思路,1.找子问题,“求以ak(k=1,2,3N)为终点的最长上升子序列的,长度”,一个上升子序列中最右边的那个数,称为该子序列的,“终点”。,虽然这个子问题和原问题形式上并不完全一样,但,是只要这N个子问题都解决了,那么这N个子问题的解中,最大的那个就是整个问题的解。,2.确定状态:,子问题只和一个变量-数字的位置相关。因此序列中数,的位置k 就是“状

16、态”,而状态 k 对应的“值”,就是以ak,做为“终点”的最长上升子序列的长度。,状态一共有N个。,3.找出状态转移方程:,maxLen(k)表示以ak做为“终点”的,最长上升子序列的长度那么:,初始状态:maxLen(1)=1,maxLen(k)=max maxLen(i):1=i k 且 ai ak且 k1+1,若找不到这样的i,则maxLen(k)=1,maxLen(k)的值,就是在ak左边,“终点”数值小于ak,且长度最大的那个上升子序列的长度再加1。因为ak左边任何“终点”小于ak的子序列,加上ak后就能形成一个更长的上升子序列。,#include#include#include u

17、sing namespace std;const int,int aMAXN;int main()int N;,int maxLenMAXN;cin N;,for(int i=1;i=N;+i),cin ai;,maxLeni=1;,for(int i=2;i aj)maxLeni=max(maxLeni,maxLenj+1);cout*max_element(maxLen+1,maxLen+N+1);return 0;,/时间复杂度O(N2),“人人为我”递推型动归程序MAXN=1010;,动归的常用两种形式,1)递归型,优点:直观,容易编写,缺点:可能会因递归层数太深导致爆栈,函数调用带来

18、额外时间开销。无法使用滚动数组节省空间。总体来说,比递推型慢。,1)递推型,效率高,有可能使用滚动数组节省空间,例三、最长公共子序列,给出两个字符串,求出这样的一,个最长的公共子序列的长度:子序列中的每个字符都能在两个原串中找到,而且每个字符的先后顺序和原串中的先后顺序一致。,最长公共子序列,Sample Inputabcfbc abfcabprogramming contestabcd mnpSample Output420,字符形成的子串的最长公共子序列的长度(i,j从0开始算)MaxLen(i,j)就是本题的“状态”假定 len1=strlen(s1),len2=strlen(s2)那么

19、题目就是要求 MaxLen(len1,len2),最长 输入两个串s1,s2,公 设MaxLen(i,j)表示:共 s1的左边i个字符形成的子串,与s2左边的j个,子序列,显然:MaxLen(n,0)=0(n=0len1)MaxLen(0,n)=0(n=0len2)递推公式:if(s1i-1=s2j-1)/s1的最左边字符是s10MaxLen(i,j)=MaxLen(i-1,j-1)+1;elseMaxLen(i,j)=Max(MaxLen(i,j-1),MaxLen(i-1,j);时间复杂度O(mn)m,n是两个字串长度,最长公共子序列,#include#include using name

20、space std;char sz11000;char sz21000;,int maxLen10001000;int main(),while(cin sz1 sz2)int length1=strlen(sz1);int length2=strlen(sz2);int nTmp;int i,j;,for(i=0;i=length1;i+),maxLeni0=0;,for(j=0;j=length2;j+),maxLen0j=0;,for(i=1;i=length1;i+)for(j=1;j=length2;j+)if(sz1i-1=sz2j-1)maxLenij=maxLeni-1j-1+

21、1;elsemaxLenij=max(maxLenij-1,maxLeni-1j);cout maxLenlength1length2 endl;return 0;,怎么输出这个最长公共子序列?,回溯输出,void LCS_LENGTH(char x,char y)int i,j,m=strlen(x),n=strlen(y);for(i=1;i=cij-1)cij=ci-1j;bij=;elsecij=cij-1;bij=;,void LCS(char x,int i,int j)if(i,有一个由1.9组成的数字串.问如果将m个加号插入到这个数字串中,在各种可能形成的表达式中,值最小的那个

22、表达式的值是多少,例四、最佳加法表达式,假定数字串长度是n,添完加号后,表达式的最后一个加号添加在第 i 个数字后面,那么整个表达式的最小值,就等于在前 i 个数字中插入 m 1个加号所能形成的最小值,加上第 i+1到第 n个数字所组成的数的值(i从1开始算)。,解题思路,总时间复杂度:O(mn2).,解题思路设V(m,n)表示在n个数字中插入m个加号所能形成的表达式最小值,那么:if m=0V(m,n)=n个数字构成的整数else if n m+1V(m,n)=elseV(m,n)=Min V(m-1,i)+Num(i+1,n)(i=m n-1)Num(i,j)表示从第i个数字到第j个数字所

23、组成的数。数字编号从1开始算。此操作复杂度是O(j-i+1),可以预处理后存起来。,总时间复杂度:O(mn2).,若 n 比较大,long long 不够存放运算过程中的整数,则需要使用高精度计算,(用数组存放大整数,模拟列竖式做加法),复杂度为O(mn3),解题思路,例五、神奇的口袋,有一个神奇的口袋,总的容积是40,用这个口袋可以变出一些物品,这些物品的总体积必须是40。John现在有n(1n 20)个想要得到的物品,每个物品的体积分别是a1,a2an。John可以从这些物品中选择一些,如果选出的物体的总体积是40,那么利用这个神奇的口袋,John就可以得到这些物品。现在的问题是,John

24、有多少种不同的选择物品的方式。,3202020,输入输入的第一行是正整数n(1=n=20),表示不同的物品的数目。接下来的n行,每行有一个1到40之间的正整数,分别给出a1,a2an的值。输出输出不同的选择物品的方式的数目。输入样例 输出样例,3,枚举每个物品是选还是不选,共220种情况,枚举的解法:,int a30;,int N;,int Ways(int w,int k)/从前k种物品中选择一些,凑成体积w的做法数目if(w=0)return 1;if(k N;for(int i=1;i ai;cout Ways(40,N);return 0;,递归解法#include using nam

25、espace std;,#include,using namespace std;int a30;int N;int Ways5040;/Waysij表示从前j种物品里凑出体积i的方法数int main()cin N;memset(Ways,0,sizeof(Ways);for(int i=1;i ai;Ways0i=1;Ways00=1;for(int w=1;w=0)Wayswk+=Waysw-akk-1;cout Ways40N;return 0;,动规解法,例六、0-1背包问题,有N件物品和一个容积为M的背包。第i件物品的体积wi,价值是di。求解将哪些物品装入背包可使价值总和最大。每

26、种物品只有一件,可以选择放或者不放(N=3500,M=13000)。,0-1背包问题,用 Fij 表示取前i种物品,使它们总体积不超过j的最优取法取得的价值总和。要求FNM,边界:if(w1=j),F1j=d1;,else,F1j=0;,0-1背包问题,用 Fij 表示取前i种物品,使它们总体积不超过j的最优取法取得的价值总和,递推:Fij=max(Fi-1j,Fi-1j-wi+di),取或不取第 i种物品,两者选优,(j-wi=0才有第二项),0-1背包问题,Fij=max(Fi-1j,Fi-1j-wi+di),本题如用记忆型递归,需要一个很大的二维数组,会超内存。注意到这个二维数组的下一行

27、的值,只用到了上一行的正上方及左边的值,因此可用滚动数组的思想,只要一行即可。即可以用一维数组,用“人人为我”递推型动归实现。,0-1背包问题,状态方程改为f(x)=maxf(x-vi)+ci,f(x)前i个物品,体积不超过x的最大价值,例七、滑雪Michael喜欢滑雪百这并不奇怪,因为滑雪的确很刺激。可是为了获得速度,滑的区域必须向下倾斜,而且当你滑到坡底,你不得不再次走上坡或者等待升降机来载你。Michael想知道载一个区域中最长的滑坡。区域由一个二维数组给出。数组的每个数字代表点的高度。下面是一个例子1 2 3 4 516 17 18 19 615 24 25 20 714 23 22

28、21 813 12 11 10 9一个人可以从某个点滑向上下左右相邻四个点之一,当且仅当高度减小。在上面的例子中,一条可滑行的滑坡为24-17-16-1。当然25-24-23-.-3-2-1更长。事实上,这是最长的一条。输入输入的第一行表示区域的行数R和列数C(1=R,C=100)。下面是R行,,每行有C个整数,代表高度h,0=h=10000。输出输出最长区域的长度。,输入输入的第一行表示区域的行数R和列数C(1=R,C=100)。下面是R行,每行有C个整数,代表高度h,0=h=10000。输出输出最长区域的长度。样例输入5 51 2 3 4 516 17 18 19 615 24 25 20

29、 714 23 22 21 813 12 11 10 9样例输出,25,L(i,j)表示从点(i,j)出发的最长滑行长度。,一个点(i,j),如果周围没有比它低的点,L(i,j)=1,否则,递推公式:L(i,j)等于(i,j)周围四个点中,比(i,j)低,且L值最大的那个点,的L值,再加1,复杂度:O(n2),解题思路,解法1)“人人为我”式递推,L(i,j)表示从点(i,j)出发的最长滑行长度。,一个点(i,j),如果周围没有比它低的点,L(i,j)=1,将所有点按高度从小到大排序。每个点的 L 值都初始化为1,从小到大遍历所有的点。经过一个点(i,j)时,用递推公式求L(i,j),解题思路,L(i+1,j)=max(L(i+1,j),L(i,j)+1),解题思路解法2)“我为人人”式递推L(i,j)表示从点(i,j)出发的最长滑行长度。一个点(i,j),如果周围没有比它低的点,L(i,j)=1将所有点按高度从小到大排序。每个点的 L 值都初始化为1从小到大遍历所有的点。经过一个点(i,j)时,要更新他周围的,比它高的点的L值。例如:if H(i+1,j)H(i,j)/H代表高度,希望大家能活学活用,掌握递归和动态规划的思想,解决问题时灵活应用,

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 生活休闲 > 在线阅读


备案号:宁ICP备20000045号-2

经营许可证:宁B2-20210002

宁公网安备 64010402000987号