动态规划总结ppt课件.ppt
《动态规划总结ppt课件.ppt》由会员分享,可在线阅读,更多相关《动态规划总结ppt课件.ppt(109页珍藏版)》请在淘文阁 - 分享文档赚钱的网站上搜索。
1、DP的复习与提高最长不下降子序列模型设有整数序列b1,b2,b3,bn, 若存在i1i2i3im, 且bi1bi2bi3bim, 则称b1,b2,b3,bn,中有长度为M的不下降序列bi1,bi2,bi3,bim。求序列b1,b2,b3,bn中所有长度(M)最大不下降序列。输入:整数序列输出:最大长度M和所有长度为M的序列个数T分析: 设h1.n表示n个输入的整数; 令fi表示从第i个数开始到第m个数的最长不下降子序列的长度,则有: fi = max(fj+1)(1=i=n-1, i+1=j=n, hi=hj) 边界为fn := 1 具体求解时用倒推,for i:=n-1 downto 1 时
2、间复杂性:O(n2)顺推的算法设f(i)为前i个数中的最大不下降序列长度 , 则 f(i)=maxf(j)+1 (1=ji=n, hjhi) 边界为F(1)=1 下面的优化算法是以顺推方向进行的.优化 如果当n=100000时,显然上述算法要超时。 从DP的基本优化思路着手,也就是去除一些一定不会有最优解产生的状态。例如:fi=3; hi=10; fj=3; hj=5,那么无论具体的搭配情况如何,状态j都要比状态i优秀。也就是说,我们只需要保留当前长度为i的序列中最后一个数字即可,并且这个数是所有长度为i的不下降序列中最后一个数的最小值。 由此,算法的本质也发生了变化。 设bi表示长度为i的不
3、下降序列的最后一个元素的最小值。 初始化:bi:=maxlongint, b1 := h1 容易看出,b数组一定是不下降序列。 当处理hi时,用二分法查找它可以连接到长度最大为多少的不下降子序列的之后(查找区间的左右边界是1i)。 假设可以连到长度最大为y的不上升子序列后,则by+1:=minby+1,hi。在找到hi的最终位置后,也就知道了前i个数的最长不下降序列的长度了,这时就可记录fi的值. 最后,b数组被赋值的元素最大下标就是问题的答案。 在实现时要仔细考虑一些细节情况.1.求最长不下降序列参考程序:const maxn=100000;var h,b,f:array1.maxn of
4、longint; n,i,j,k,l,r,m:longint; found :boolean;begin readln(n); for i:=1 to n do read(hi); for i:=1 to n do bi := maxlongint; b1 := h1; f1 := 1; for i:=2 to n do begin l:=1; r:= i; while l r do begin m := (l+r) div 2; if bm hi then begin bl := hi; fi := l; end else fi := l+1; end; j:=0; for i:=1 to
5、n do if bi maxlongint then inc(j) else break; writeln(j); for i:=1 to j do write(bi:4); writeln; for i:=1 to n do write(fi:4);end.数据f存储了以每个元素结尾的最长不下降序列的长度.注意:两个程序的主要区别在于二分查找时对于bm=hi时的处理方法不同。对于严格递增序列来说,出现相等时,不增加序列长度。对于不降序列来说,则要增加序列长度。 2. 求严格递增序列const maxn=100000;var h,b,f:array1.maxn of longint; n,i,
6、j,k,l,r,m:longint; found :boolean;begin readln(n); for i:=1 to n do read(hi); for i:=1 to n do bi := maxlongint; b1 := h1; f1 := 1; for i:=2 to n do begin l:=1; r:= i; found := false; while l hi then r := m-1 else if bm hi then begin bl := hi; fi := l; end else begin bl+1 := hi; fi := l+1; end end;
7、j:=0; for i:=1 to n do if bi maxlongint then inc(j) else break; writeln(j); for i:=1 to j do write(bi:4); writeln; for i:=1 to n do write(fi:4);end.最长不下降序列拓展1、求序列中最长不下降序列的个数。 设ti为以i结尾的最长不下降序列的个数,则 Ti=tj (1=ji=n , hj=hi, fi=fj+1) 边界为:t1=1 当fi=n时,将ti累加 举例: h: 1 2 3 4 6 5 8 10 9 f: 1 2 3 4 5 5 6 7 7 t:
8、 1 1 1 1 1 1 2 2 2答案:f=7时,个数为t=4最长不下降序列拓展2、求本质不同的最长不下降序列的个数。(注:其实这里讨论的是单调递增序列)求本质不同的最长不下降序列个数有多少个?如:1 2 3 4 6 5 8 10 9 有, 1 2 3 4 6 8 10 , 1 2 3 4 5 8 10, 1 2 3 4 6 8 9 ,1 2 3 4 5 8 9 都是本质不同的。但对于 h 1 2 2 3 3 5 4 5 f 1 2 2 3 3 4 4 4 t 1 1 1 2 2 4 4 4 答案有8个,其中4个1 2 3 5 ,4个1 2 3 4正确答案应该是两个.上例显然对于原序列h中两
9、个相同的数,重复算了多次因此,我们对算法进行改进:对原序列按h从小到大(当hi=hj时按F从大到小)排序,增设Orderi记录新序列中的i个数在原序列中的位置。可见,求ti时,当fj=fj+1,hj=hj+1且Orderj+1Orderi时,便不累加tj。这样就避免了重复。 上述算法的时间复杂度为O(n2) 这个算法也存在问题.对于 h 1 2 2 3 3 5 4 5 f 1 2 2 3 3 4 4 4 t 1 1 1 2 2 4 4 4将得出3的错误答案如果改为统计最后结果时要求(fi = fj = maxlen) 且 (hi hj),则下面的数据又会出现错误答案: h 1 3 4 5 1
10、2 3 5 f 1 2 3 4 1 2 3 4 程序输出为1正确应该是2错误程序1: 按PPT中的算法执行const maxn=10000;var h,f,t,order:array1.maxn of longint; n,i,j,k,max, mlen:longint;procedure swap(var a,b:longint);var x:longint;begin x:= a; a:=b; b:=x;end;begin readln(n); for i:=1 to n do read(hi); mlen:=0; for i:=1 to n do begin read(fi); if f
11、i mlen then mlen := fi; end; for i:=1 to n+1 do orderi := i; hn+1 := maxlongint; fn+1 := mlen+1; inc(n); for i:=1 to n-1 do for j:=n downto i+1 do if hj-1 hj then begin swap(hj-1,hj); swap(fj-1,fj); swap(orderj-1,orderj); end else if hj-1 = hj then begin if fj-1 fj then begin swap(hj-1,hj); swap(fj-
12、1,fj); swap(orderj-1,orderj); end; end; t1 := 1; for i:=2 to n do for j:= i-1 downto 1 do if (hj hi) and (fj+1 = fi) then if not ( hj=hj+1) and (fj=fj+1) and(orderj+1 mlen then mlen := fi; end; for i:=1 to n+1 do orderi := i; hn+1 := maxlongint; fn+1 := mlen+1; inc(n); for i:=1 to n do if fi = 1 the
13、n ti := 1; for k:=2 to mlen+1 do for i:=n downto 1 do if fi = k then begin j:=i-1; while (j0) and (hj hi ) do begin if (hj mlen then mlen := fi; end; for i:=1 to n+1 do orderi := i; hn+1 := maxlongint; /建立哨兵 fn+1 := mlen+1; inc(n); t1:=1; /前一个程序中仅有的改动 for k:=2 to mlen+1 do for i:=n downto 1 do if fi
14、 = k then begin j:=i-1; while (j0) and (hj hi ) do begin if (hj hi) and (fj+1=k) then inc(ti, tj); dec(j); end; end; writeln(tn);end.测试数据71 2 2 3 3 5 41 2 2 3 4 4 491 2 3 4 6 5 8 10 91 2 3 4 5 5 6 7 781 2 2 3 3 5 4 51 2 2 3 4 4 4 58 1 2 1 2 3 3 5 41 2 1 2 3 3 4 4 81 3 4 5 1 2 3 51 2 3 4 1 2 3 4但这组数据
15、过不了:82 3 4 5 1 2 3 51 2 3 4 1 2 3 4经典赛题1、导弹拦截(注意:第二问不可以用每次删除最长不上升序列的方法做。比如,当来袭的导弹共有4颗,高度依次为2 4 1 3的时候,如果不巧找到的最长不上升序列为4 1,那么剩下的2和3就只能另外启用两套系统了。这显然不是最优解。 ) 第二问用贪心法即可。每颗导弹来袭时,使用能拦截这颗导弹的防御系统中上一次拦截导弹高度最低的那一套来拦截。若不存在符合这一条件的系统,则使用一套新系统。 合唱队形合唱队形【问题描述【问题描述】N位同学站成一排,音乐老师要请其中的(N-K)位同学出列,使得剩下的K位同学排成合唱队形。合唱队形是指
16、这样的一种队形:设K位同学从左到右依次编号为1, 2, , K,他们的身高分别为T1, T2, , TK,则他们的身高满足T1 T2 Ti+1 TK (1iK)。你的任务是,已知所有N位同学的身高,计算最少需要几位同学出列,可以使得剩下的同学排成合唱队形。输入文件输入文件chorus.in的第一行是一个整数N(2=N=100),表示同学的总数。第一行有n个整数,用空格分隔,第i个整数Ti(130=Ti=230)是第i位同学的身高(厘米)。-输出文件输出文件chorus.out包括一行,这一行只包含一个整数,就是最少需要几位同学出列。-样例输入8186186150200160130197220-
17、样例输出4 设有N*N的方格图(N=10,我们将其中的某些方格中填入正整数,而其他的方格中则放入数字0。如下图所示(见样例):方格取数?(可以用最长不下降模型吗?)方格取数?(可以用最长不下降模型吗?)对比对比VIJOS 飞翔飞翔飞翔飞翔 http:/:8080/JudgeOnline/showproblem?problem_id=1907某人从图的左上角的A 点出发,可以向下行走,也可以向右走,直到到达右下角的B点。在走过的路上,他可以取走方格中的数(取走后的方格中将变为数字0)。此人从A点到B 点共走两次,试找出2条这样的路径,使得取得的数之和为最大。 输输 入入 输入的第一行为一个整数N
18、(表示N*N的方格图),接下来的每行有三个整数,前两个表示位置,第三个数为该位置上所放的数。一行单独的0表示输入结束。 输输 出出 只需输出一个整数,表示2条路径上取得的最大的和。后面是另外思路的DP参考解答分析: 这是一道所谓”路径”类型的DP题.这道题的阶段划分方法有两种:较为简单的一种是按行划分阶段,按列划分状态. 如果人只从A点到B点走一次,则可以用DP较方便的解决:从A开始,向下向下递推,依次求出从A点出发到达当前位置(i,j)所能取得的最大的数之和,存放在sum数组中.原始数据存放在data数组中.为处理方便, sum数组加进了0行和0列. 状态转移方程为: Sumi,j = ma
19、xsumi-1,j, sumi,j-1 + datai,j (1=i=n, 1=j=n)如果走两次,能不能够用DP先走一次,求得最大数和, 把路径上的数清0,然后再用DP走一次,求得第二最大数和,再把两次的结果相加得到最后的结果呢?这是一种很自然的想法,并且对测试样例也是正确的.但实际这种算法是错误的.例如,对右图数据,若按DP先走一次,将取完红色字体的数,但第二次DP时,两个黑色的数字将无法同时取到.而事实我们可以简单地将第3列和第5列的所有数取完.因此本题所谓走两次其实必须在一次DP时同时考察两条路径.3233443考虑两个人同时从A出发,则需要考虑两个人到达任意两个格子(i1,j1)(i
20、2,j2)的情况.即状态要用4个变量来描述:sumi1,j1,i2,j2每个人可以从上或左的两个方向达到当前格子,显然前一状态必为:(i1-1,j1), (i2-1,j2)(i1-1,j1),(i2, j2-1)(i1,j1-1),(i2-1,j2)(i1,j1-1),(i2,j2-1)四种情况之一.设p=maxsumi1-1,j1, i2-1,j2, sumi1-1,j1,i2, j2-1, sumi1,j1-1,i2-1,j2,sumi1,j1-1,i2,j2-1则有j2)j1or i2(i1 j2datai2, j1datai1, pj2)j1 and i2(i1 j1datai1,p2
21、j2,i1,j1,sumi据此,可写出程序.易知,本算法的时间空间复杂度均为O(n4)后一段分析是按对角线方向来划分阶段的.这样处理之后, 可以把时间复杂性降低一维,把空间复杂性降低到O(n2), 因此该思想方法要认真思考, 掌握优化方法优化方法: 1、状态的设计、状态的设计 对于本题来说,状态的选定和存储对整个问题的处理起了决定性的作用。我们从(1,1)出发,每走一步作为一个阶段,则可以分成2*n-1个阶段: 第一个阶段,两条路径从(1,1)出发; 第二个阶段,两条路径可达(2,1)和(1,2); 第三个阶段,两条路径可达的位置集合为(3,1)、(2,2)和(1,3); 第2*n-1个阶段,
22、两条路径汇聚(n,n);在第k(1k2*n-1)个阶段,两条路径的终端坐标(x1,y1)(x2,y2)位于对应的右下对角线上。如下图所示:阶段1阶段2 阶段3 阶段4阶段5阶段6阶段7如果我们将两条路径走第i步的所有可能位置定义为当前阶段的状态的话,面对的问题就是如何存储状态了。方格取数问题的状态数目十分庞大,每一个位置是两维的,且又是求两条最佳路径,这就要求在存储上必须做一定的优化后才有可能实现算法的程序化。主要的优化就是:舍弃一切不必要的存储量。为此,我们取位置中的x坐标(x1,x2)作状态,其中(1x1n)and(1x2n)直接由x坐标计算对应的y坐标:(y1=k+1-x1)and(y1
23、1n)and(y2=k+1-x2)and(y21n 阶段1阶段2 阶段3 阶段4阶段5阶段6阶段72、状态转移方程、状态转移方程设两条路径在k阶段的状态为(x1,x2)。由(y1=k+1-x1)(y1 1.n)得出第一条路径的坐标为(x1,y1);由(y2=k+1-x2)(y2 1.n)得出第二条路径的坐标为(x2,y2)。假设在k-1阶段,两条路径的状态为(x1,x2)且(x1,x2)位于(x1,x2)状态的左邻或上邻位置。因此我们设两条路径的延伸方向为d1和d2:di=0,表明第i条路径由(xi,yi)向右延伸至(xi,yi);di=1,表明第i条路径由(xi,yi)向下延伸至(xi,yi
24、)(1i2)。显然(x1= x2)(d1= d2),表明两条路径重合,同时取走了(x1,y1)和(x1,y1)中的数,这种取法当然不可能得到最大数和的。分析两种可能:若x1=x2,则两条路径会合于x1状态,可取走(x1,y1)中的数(如下图); x2(x1) x1(x2) x1=x2 若x1x2,则在k阶段,第一条路径由x1状态延伸至x1状态,第二条路径由x2状态延伸至x2状态,两条路径可分别取走(x1,y1)和(x2,y2)中的数(如下图);X1X1X2X2设 fk,x1,x2在第k阶段,两条路径分别行至x1状态和x2状态的最大数和。显然k=1时,时,f1,1,1=data1,1;k2时,时
25、,fk,x1,x2=maxfk-1, x1,x2+datax1,y1(x1=x2),fk-1, x1,x2+datax1,y1+datax2,y2(x1x2) 1k2*n-1,x1可达可达x1的状态集合,的状态集合,x2可达可达x2的状态集合,(的状态集合,(x1x2)(d1d2);上述状态转移方程符合最优子结构和重叠子问题的特性,因此适用于动态程序设计方法求解。由于第由于第k个阶段的状态转移方程仅与第个阶段的状态转移方程仅与第k-1个阶段的状态发生联系个阶段的状态发生联系,因此不妨设 f0第k-1个阶段的状态转移方程; f1第k个阶段的状态转移方程;初始时,f01,1=0。经过2*n-1个阶
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 动态 规划 总结 ppt 课件
限制150内