1、动态规划(1) (Dynamic programming),用递推代替递归用空间换时间,北大李文新程序设计导引及在线时间第10章,先热身一下,海盗分金问题,5名海盗抢得了窖藏的100块金子,并打算瓜分这些战利品。这是一些讲民主的海盗(当然是他们自己特有的民主),他们的习惯是按下面的方式进行分配:最厉害的一名海盗提出分配方案,然后所有的海盗(包括提出方案者本人)就此方案进行表决。如果50%或更多的海盗赞同此方案,此方案就获得通过并据此分配战利品。否则提出方案的海盗将被扔到海里,然后下一名最厉害的海盗又重复上述过程。,所有的海盗都乐于看到他们的一位同伙被扔进海里,不过,如果让他们选择的话,他们还是
2、宁可得一笔现金。他们当然也不愿意自己被扔到海里。所有的海盗都是聪明绝顶的,而且知道其他的海盗也是聪明绝顶的。此外,没有两名海盗是同等厉害的这些海盗按照完全由上到下的等级排好了座次,并且每个人都清楚自己和其他所有人的等级。这些金块不能再分,也不允许几名海盗共有金块,因为任何海盗都不相信他的同伙会遵守关于共享金块的安排。这是一伙每人都只为自己打算的海盗。,最凶的一名海盗应当提出什么样的分配方案才能使他获得最多的金子呢?我们按照这些海盗的威望值来给他们编号。最怯懦的海盗为1,最厉害的海盗编号为5。编号为5的海盗会提出什么分配方案呢?,如果从游戏的开头出发进行分析,那是走不了多远的。其原因在于,所有的
3、战略决策都是要确定:“如果我这样做,那么下一个人会怎样做?”因此在你以下海盗所做的决定对你来说是重要的,而在你之前的海盗所做的决定并不重要,因为你反正对这些决定也无能为力了。,最厉害的5号海盗需要知道其他4名海盗是怎么想的.好难猜!对4号海盗来说,如果5号海盗被扔进海里喂鲨鱼了,他只需要猜透其余3名海盗的算盘。对3号海盗而言,他只须猜透1号和2号海盗对2号海盗而言,他只须猜透1号海盗那我们就倒过来,由易到难,我们的出发点应当是游戏进行到只剩两名海盗即1号和2号的时候。这时最厉害的海盗是2号,而他的最佳分配方案是一目了然的:100块金子全归他一人所有,1号海盗什么也得不到。3号海盗的分配方案:3
4、号海盗分得99块金子,2号海盗一无所获,1号海盗得1块金子。,1号海盗知道,如果3号的方案被否决,那么最后将只剩2个海盗,而1号将肯定一无所获此外,3号也明白1号了解这一形势。因此,只要3号的分配方案给1号一点甜头使他不至于空手而归,那么不论3号提出什么样的分配方案,1号都将投赞成票。因此3号需要分出尽可能少的一点金子来贿赂1号海盗,4号的分配方案应是:99块金子归自己,3号一块也得不到,2号得1块金子,1号也是一块也得不到。,4号海盗的策略也差不多。他需要有50%的支持票,因此同3号一样也需再找一人做同党。他可以给同党的最低贿赂是1块金子,而他可以用这块金子来收买2号海盗。因为如果4号被否决
5、而3号得以通过,则2号将一文不名。,5号海盗的分配方案应该是:98块金子归自己,1块金子给3号,1块金子给1号。,5号海盗的策略稍有不同。他需要收买另两名海盗,因此至少得用2块金子来贿赂,才能使自己的方案得到采纳。,讨论:为什么贿赂1号和3号而不是4号和2号?,总结分析所有这类策略游戏的奥妙就在于应当从结尾出发倒推回去。游戏结束时,你容易知道何种决策有利而何种决策不利。,在现实生活中,有一类活动的过程,由于它的特殊性,可将过程分成若干个互相联系的阶段,在它的每一阶段都需要作出决策,从而使整个过程达到最好的活动效果。这种把一个问题看作是一个前后关联具有链状结构的多阶段过程就称为多阶段决策过程,这
6、种问题称为多阶段决策问题。,多阶段决策问题,10.1 什么是动态规划,1、最短路径问题2、数塔问题,下图表示城市之间的交通路网,线段上的数字表示费用,单向通行由A-E。试用动态规划的最优化原理求出A-E的最省费用。,1 最短距离问题,如图从A到E共分为4个阶段,即第一阶段从A到B,第二阶段从B到C,第三阶段从C到D,第四阶段从D到E。 除起点A和终点E外,其它各点既是上一阶段的终点又是下一阶段的起点。,例如从A到B的第一阶段中,A为起点,终点有B1,B2两个,因而这时走的路线有两个选择,一是走到B1,一是走到B2。,若选择B2的决策,B2就是第一阶段在我们决策之下的结果,它既是第一阶段路线的终
7、点,又是第二阶段路线的始点。,在第二阶段,再从B2点出发,对于B2点就有一个可供选择的终点集合(C1,C2,C3);若选择由B2走至C2为第二阶段的决策,则C2就是第二阶段的终点,同时又是第三阶段的始点。,同理递推下去,可看到各个阶段的决策不同,线路就不同。,很明显,当某阶段的起点给定时,它直接影响着后面各阶段的行进路线和整个路线的长短。 故此问题的要求是:在各个阶段选取一个恰当的决策,使由这些决策组成的一个决策序列所决定的一条路线,其总路程最短。如何解决这个问题呢?,要求在各阶段选取一个恰当的决策,决策过程:(1)由目标状态E向前推,可以分成四个阶段,即四个子问题。 DE CE BE AE(
8、2)策略:每个阶段到E的最省费用为本阶段的决策路径。,用动态规划法求解,(3)D1,D2是第一次输入的结点。他们到E都只有一种费用: f(D1)=5 f(D2)=2,目前无法定下,哪一个点将在全程最优策略的路径上。第二阶段计算中,5,2都应分别参加计算,(4)C1,C2,C3是第二次输入结点,他们到D1,D2各有两种费用。此时应计算C1,C2,C3分别到E的最少费用。 f(C1) =minC1D1+ f(D1) ,C1D2+ f(D2)。 计算结果是f(C1)= C1D1+ f(D1)=8 (D1)同理C2的决策路径计算结果是C2+D2+ E , f(C2)=7 。同理C3的决策路径计算结果是
9、C3+D2+E,f(C3)=10。,(5)第三次输入结点为B1,B2,而决策输出结点可能为C1,C2,C3。仿前计算可得Bl,B2的决策路径为如下情况。Bl: B1C1 费用 f(B1)=5+8=13, B2:B2C1 费用 f(B2)= 6+8=14,,(6)第四次输入结点为A,决策输出结点可能为B1,B2。 同理可得决策路径为A:AB2,费用5+14=19此时才正式确定每个子问题的结点中,那一个结点将在最优费用的路径上。 子问题的决策中,只对同一城市(结点)比较优劣。而同一阶段的城市(结点)的优劣要由下一个阶段去决定。,2、数塔问题,有形如下图所示的数塔,从顶部出发,在每一结点可以选择向左
10、走或是向右走,一直走到底层,要求找出一条路径,使路径上的值最大。,用暴力的方法,可以吗?,这道题如果用枚举法(暴力思想),在数塔层数稍大的情况下(如31),则需要列举出的路径条数将是一个非常庞大的数目(230= 10243 109=10亿)。,试想一下:,拒绝暴力,倡导和谐,从顶点出发时到底向左走还是向右走应取决于是从左走能取到最大值还是从右走能取到最大值,只要左右两道路径上的最大值求出来了才能作出决策。可见,由下层的子问题可以得到上层的子问题,所以,可从底层开始,层层递进,最后得到最大值。结论:自顶向下的分析,自底向上的计算。,考虑一下:,21,28,19,21,38,34,29,50,49
11、,59,自底向上计算,自顶向下决策,如果各个子问题不是独立的,不同的子问题的个数只是多项式量级,如果我们能够保存已经解决的子问题的答案,而在需要的时候再找出已求得的答案,这样就可以避免大量的重复计算。由此而来的基本思路是,用一个表记录所有已解决的子问题的答案,不管该问题以后是否被用到,只要它被计算过,就将其结果填入表中。,10.2 动态规划的基本思想,动态规划的基本步骤,动态规划算法通常用于求解具有某种最优性质的问题。在这类问题中,可能会有许多可行解。每一个解都对应于一个值,我们希望找到具有最优值(最大值或最小值)的那个解。设计一个动态规划算法,通常可以按以下几个步骤进行:,(1)找出最优解的
12、性质,并刻画其结构特征。(2)递归地定义最优值。(3)以自底向上的方式计算出最优值。(4)根据计算最优值时得到的信息,构造一个最优解。其中(1)(3)步是动态规划算法的基本步骤。在只需要求出最优值的情形,步骤(4)可以省去。若需要求出问题的一个最优解,则必须执行步骤(4)。此时,在步骤(3)中计算最优值时,通常需记录更多的信息,以便在步骤(4)中,根据所记录的信息,快速构造出一个最优解。,基本步骤,动态规划问题的特征,动态规划算法的有效性依赖于问题本身所具有的两个重要性质:1、最优子结构:当问题的最优解包含了其子问题的最优解时,称该问题具有最优子结构性质。2、重叠子问题:在用递归算法自顶向下解
13、问题时,每次产生的子问题并不总是新问题,有些子问题被反复计算多次。动态规划算法正是利用了这种子问题的重叠性质,对每一个子问题只解一次,而后将其解保存在一个表格中,在以后尽可能多地利用这些子问题的解。,练习,游戏币迷宫赤驴小兔的棋盘,10.3 最长有序子序列,子问题的构造,子问题“求以ak(k=1, 2, 3N)为终点的最长上升子序列的长度” 虽然这个子问题和原问题形式上并不完全一样,但是只要这N 个子问题都解决了,那么这N 个子问题的解中,最大的那个就是整个问题的解。该子问题可以递推求解,假定MaxLen (k)表示以ak 做为“终点”的最长上升子序列的长度,那么:MaxLen (1) = 1
14、MaxLen (k) = Max MaxLen (i):1i k 且 ai ak 且 k1 + 1,实例:,所求最大值是Fn吗?,2,hdu1160 FatMouses Speed,Sample Input6008 1300 6000 2100 500 2000 1000 4000 1100 3000 6000 2000 8000 1400 6000 1200 2000 1900,Sample Output4 4 5 9 7,题目分析:,设Micei.W表示第i只老鼠的重量,Micei.S表示第i只老鼠的速度。我们先对Mice进行排序,以W为第一关键字,从小到大,S为第二关键字,从大到小。设f
15、i为Micei至Micen最长的序列长度。考虑某一个fi,则有: fi = max( fi , fj+1) (1 Micej.W,Micei.S =cij-1 cij=ci-1j; 否则 cij=cij-1;,LCS(Xm,Yn)= LCS(Xm,Yn)+xm,例:X=A B C B D A B Y=B D C A B A,0 B D C A B A,0ABCBDAB,AABABCABCBABCBDABCBDAABCBDAB, B BD BDC ,例:X=A B C B D A B Y=B D C A B A,0 B D C A B A,0ABCBDAB,void LCS(int m,int
16、n,char *x, char *y, char *z ,int *c)/不用数组b,构造最优解的非递归算法 int i=m,j=n; int k=cmn; /最长公共子序列的长度 while(i0,构造最长公共子序列,10.5 0-1背包问题,给定n种物品和一背包。物品i的重量是wi,其价值为vi,背包的容量为C。问应如何选择装入背包的物品,使得装入背包中物品的总价值最大?目标:使装入背包中物品的总价值最大约束条件:装入的物品总重不得超过C,海盗盗宝问题,海盗有一背包,最大容积为9,现有5件宝物: 体积si分别是2、3、4、5和4公斤 价值vi分别是3、7、5、9和 8 请给出装载方案,使背
17、包价值达到最大。,C=9,一开始,见物品就装,物品1、2、3全装入,背包装满了,得到背包总价值为15,这是不是最大价值呢?,考虑只有前三个物品的情况,物品4该不该装?有两个选择:(1)不装,背包价值不变,为15,(2)装入,它占去的体积为5,得到价值为9,剩下容积4最多可以装下多大价值?,考虑只有前4个物品的情况,这是一个n=3(从前三个物品中选择),容量c=4的子问题。,目前最优:装入物品2和物品4,总价值为16,若已知这个子问题的解是:装物品2,得价值为7。,(2)装入物品4,它占去的体积为5,得到价值为9,剩下容积4最多可以装下多大价值?,考虑5个物品的情况,物品5该不该装?(1)不装,
18、得到背包价值仍为16,(2)若装入物品5,占用体积为4,得价值为8,背包剩余容积为5。 如何在前4个物品中选择装入,使背包价值最大化?这是n=4,c=5的一个子问题。 若得到该子问题的解为:装入物品1、2,得价值为10,考虑5个物品的情况,目前最优:装入物品5和1、2,总价值为1816,子问题的构造,当n=1时:只有一个物品, s1=2,v1=3 若背包容量c=0、1,则无法装入物品1,得到背包价值为0若背包容量c=2、3、4、5、6,7,8,9则可装入物品1,得到背包价值为3。,C10=0 C11=0 C12=3 C13=3 C14=3 C15=3 C16=3 C17=3 C18=3 C19
19、=3,考虑两个物品的情况,当n=2时,有两个物品, s1=2,v1=3,s2=3,v2=7 若背包容量c=0、1,得到背包价值为0若背包容量c=2,可装入物品1,得总价值m22=3若背包容量c=3,m23=7,若背包容量c=4, m24=7若背包容量c=5, m25=10,若不装物品2,m23=m13=3若装入物品2,m23=v2+m13-3=7+0=7,m26=10 m27=10 m28=10 m29=10,若不装物品2,m25=m15=3若装入物品2,m25=v2+m15-3=7+3=7,递推关系的建立,用mij来表示从前i个物品中选取物品装入容量为j的背包所得的最大价值。则要寻求的是mn
20、c。mij是以下两个值的最大值(1) mi-1j: 即不装入物品i,背包价值与仅考虑前i-1个物品时情况相同; (2)vi+mi-1j-si:即装入物品i,再从前i-1个物品中选取,使背包剩余容积j-si价值最大化。,构造价值数组,背包容量j,从前i个物品中选取,背包容量j,从前i个物品中选取,构造最优解,因m59m49, 物品5被装入,剩余c=9-s5=5因m45m35, 物品4被装入,剩余c=9-s4=0,void Knapsack(int t v,int w,int c,int n,float mN)/构造价值数组m int i, j;for(i=0; i mi-1j) mij=t; e
21、lse mij=mi-1j; ,/计算最后一行的mnct= vn+ mn-1c-wn;If ( t mn-1c ) mnc=telse mnc=mn-1c;,Hdu1176 免费馅饼,输入输出,输入数据有多组。每组数据的第一行为以正整数n(0n100000),表示有n个馅饼掉在这条小径上。在结下来的n行中,每行有两个整数x,T(0T100000),表示在第T秒有一个馅饼掉在x点上。同一秒钟在同一点上可能掉下多个馅饼。n=0时输入结束。输出:每一组输入数据对应一行输出。输出一个整数m,表示gameboy最多可能接到m个馅饼,问题分析,(1)输入信息包含这个时刻和位置坐标,如何存储这些信息?还有它
22、不一定按时间顺序输入的问题 (2)子问题的建立可以正推:第1秒能接住几个?第2秒能接住几个 .也可以倒推: 最后一秒能接住几个、最后2秒能接住几个?.还有第i秒他所处的位置也影响结果,所以子问题是二维的。,输入样例111 41 5 1 62 72 72 82 81 72 81 73 8输出样例:4,实现分析,(1)初始化 先把每个时间点每个位置上降落馅饼数填充到二维数组中,作为初始值;同一时间同一地点降落多个馅饼它是可以同时得到的; 同时记下最大时刻maxT(2)递推: 倒推正推都可以,正推的话需要前四行的特殊处理。因为一开始他在位置5,第一秒根本到不了位置0.3、7.10,第二秒也根本到不了
23、位置0.2、8.10 /第三秒也到不了位置0.1、 9.10,第四秒到不了0、10 。 倒推的话,不需要对这四行进行特殊处理,最后输出t05d的值就可以了。故 本例采用倒推,初始化,0 1 2 3 4 5 6 7 8 9 10,01234567,读入馅饼个数n和n个馅饼的下落时间和位置,初始化二维数组,饼记下最大时间(即循环时的最大行号),子问题的构造,子问题:最后1秒最多能接住几个,最后两秒、最后两秒.还与当时他站的位置有关子问题是二维的: Tij表示第i秒若站在位置j,从第i秒之后能接住多少个馅饼,Tij表示第i秒若站在位置j,从第i秒之后能接住多少个馅饼Tij:若第i+1秒站在位置j,那
24、么第i秒他可能到达的位置是j-1,j,j+1,去那个位置接到馅饼最多? T(i,j-1) Tij =Ti+1j+max T(i,j) T(i,j+1),再考虑一下j=0和j=10的情况即可,0 1 2 3 4 5 6 7 8 9 10,01234567,递推,Hdu1466 计算直线的交点数,问题描述: 平面上有n条直线,且无三线共点,问这些直线能有多少种不同交点数。输入:n(n=20)输出:每个测试实例对应一行输出,从小到大列出所有相交方案,其中每个数为可能的交点数。样例输入4样例输出0 3 4 5 6,初步分析:,我们知道:n条直线互不平行且无三线共点的最多交点数max=1+2+(n-1)
25、=n(n-1)/2,但本题不这么简单,因为问题问的是:这些直线有多少种不同的交点数?,然后,假设=n-1的情况f(1),f(2),.,f(n-1)都已经知道,分析思路,首先,容易列举出N=1,2,3的情况:00,10,2,3,先来看个统计的方法:我们来分析加入第n条直线的情况分类:与第n条直线相交的分为一组(有r条) ,与其平行的在另一组(n-r条)n条直线的交点方案数= (n-r)条平行线与r条直线交叉的交点数 + r条直线本身的交点方案f(n)= (n-r)*r + f(r),r=0,1,.n-1,重点分析n的情况:,我们来分析加入第N条直线的情况(这里以N=4为例):1、第四条与其余直线
26、全部平行,即r=0 ,交点数为 4*0+0=0;2、第四条与其中1条相交,与另2条平行,即r=1 交点数为 (n-1)*1+0=3;3、第四条与其中2条相交,与另1条平行,即r=2,这两条平行直线和另外两条直线的交点数为(n-2)*2=4,而另外两条直线既可能平行也可能相交,因此可能交点数为:(n-2)*2+0=4 或者 (n-2)*2+1=5 4、 第四条直线与其余3条都相交,即r=3,交点数为: (n-3)*3+0=3 或(n-3)*3+2=5 或(n-3)*3+3=6即n=4时,有0个,3个,4个,5个,6个不同交点数。,重点分析n的情况:,用二维数组存放中间结果。数组a初始化为0.ai
27、j=1表示j是i条直线的可能交点数,第i行所有为1的元素的列号即i条直线的所有可能交点数 原问题的解就是输出数组a的第n行中,所有值为1的元素的列号j,实现问题,0 1 2 3 4 5 6 7 8 9 10,01234567,实现问题,第i行怎么填充?,(1)都不与第i条相交,r=0: 若第0行第j列为1,则第i行的j+0*i列为1(2)1条与第i条相交,r=1: 若第1行第j列为1,则第i行的j+ 1*(i-1)列为1(3)2条与第i条相交,r=2: 第2行+2*(i-2) 若第2行第j列为1,则第i行的j+ 2*(i-2)列为1.,for r=0,1i-1 /若有r条与第i条相交,其余平行 for j=0,1,. r*(r-1)/2 /r条直线最多可能交点数 若第r行第j列为1,则第i行的j+ r*(i-r)列为1,课后任务:,一、DIY在线作业(4):2008ACM ProgrammingExercise(4)_动态规划二、常规练习(包含以上作业)1003、1466 、1087、1159、1176、1058、1069、2059、2084、2151,