动态规划入门论文设计Word下载.docx
- 文档编号:18591011
- 上传时间:2022-12-28
- 格式:DOCX
- 页数:9
- 大小:69.69KB
动态规划入门论文设计Word下载.docx
《动态规划入门论文设计Word下载.docx》由会员分享,可在线阅读,更多相关《动态规划入门论文设计Word下载.docx(9页珍藏版)》请在冰豆网上搜索。
阶段:
根据问题的特点和需要,将问题按时间或空间特征分解为若干相互联系的阶段。
在本例中,我们根据空间特性将问题分成了6个阶段。
状态:
各阶段的开始条件,本例中,A,B,C……P这些节点都属于状态,表示从该点到B的最短路径,在这里我们计做S(i),表示从第i个节点(状态)到B的最短路径
决策:
某阶段状态确定后,从该状态到下阶段某状态的选择。
比如S(A),它可以选择通过C到达B,也可以选择通过D到达B。
状态转移方程:
系统由某阶段的一个状态转变到下一阶段的另一状态称状态转移,体现转移规律的方程称状态转移方程。
在本例中,我们不难推出S(A)=MIN{S(C)+4,S(D)+3},S(C)=MIN{S(E)+5,S(F)+3}…………S(B)=0,由此我们可以得出状态转移方程S(i)=MIN{S(j)+Vij}(j为与i相邻接的节点,Vij表示邻接节点i,j之间的距离)。
一个动态规划模型应该满足以下几个性质:
1.最优子结构性质
最优子结构可这样阐述:
一个最优化策略具有这样的性质,不论过去状态和决策如何,对前面的决策所形成的状态而言,余下的诸决策必须构成最优策略。
简而言之,一个最优化策略的子策略总是最优的。
例如在图2的模型中,S(A)是A到B的最短路径(最优策略),而它所依赖的S(C)和S(D)作为S(A)的子策略分别是C到B的最短路径和D到B的最短路径,也是最优的。
因此根据最优子结构性质我们得出了上面的状态转移方程。
证明:
如图2设路线W1={(A,C),(C,F),(F,J)}
W2={(J,M),(M,O),(O,B)}
若路线W1和W2是A到B的最优路径,则根据最优化原理,路线W2必是从J到B的最优路线。
用反证法证明:
假设有另一路径W2'
是J到B的最优路径,则A到B的路线取W1和W2'
比W1和W2更优,矛盾。
从而证明W2'
必是J到B的最优路径W2。
最优子结构性质是动态规划的基础,任何问题,如果失去了最优子结构性质的支持,就不可能用动态规划方法计算。
根据最优子结构性质导出的动态规划状态转移方程是解决一切动态规划问题的基本方法。
可以看出,图2的模型是满足最优子结构性质的。
2.子问题重叠性质
在我们根据状态转移方程用递归算法自顶向下对问题进行求解时,每次产生的子问题并不总是新的,而且某些子问题会被重复计算多次,比如,在求S(C)时需要递归求出S(F)的值,而在求S(D)时也需要递归求出S(F)的值,因此整个求解过程中S(F)的值会被求解两次,如果我们能把这多余的一次重复计算剔除,将可以最大程度的提高程序执行效率;
动态规划正是利用了这种子问题的重叠性质,对每个子问题只计算一次,然后将其结果保存在一个表格中,当再次需要计算已经计算过的子问题时,只是在表格中简单的查询一下结果,从而获得较高的解题效率,这个方法就是我们常说的记忆化搜索。
因此,如果我们把第一次求解出的S(F)的值用一种数据结构保存下来,下次再用到S(F)时,我们直接去查,这样能使程序的时间和空间效率将会大大提高。
。
下面通过对具体实例的分析,帮助大家领会动态规划的这两个性质和动态规划的算法设计思想
例:
导弹拦截
某国为了防御敌国的导弹袭击,发展出一种导弹拦截系统.但是这种导弹拦截系统有一个缺陷:
虽然它的第一发炮弹能够到达任意的高度,但是以后每一发炮弹都不能高于前一发的高度.某天,雷达捕捉到敌国的导弹来袭.由于该系统还在试用阶段,所以只有一套系统,因此有可能不能拦截所有的导弹.
输入导弹依次飞来的高度(雷达给出的高度数据是不大于30000的正整数),计算这套系统最多能拦截多少导弹,并依次输出被拦截的导弹飞来时候的高度.
样例:
INPUT
38920715530029917015865
OUTPUT
6(最多能拦截的导弹数)
38930029917015865
分析:
因为只有一套导弹拦截系统,并且这套系统除了第一发炮弹能到达任意高度外,以后的每一发炮弹都不能高于前一发炮弹的高度;
所以,被拦截的导弹应该按飞来的高度组成一个非递增序列.题目要求我们计算这套系统最多能拦截的导弹数,并依次输出被拦截导弹的高度,实际上就是要求我们在导弹依次飞来的高度序列中寻找一个最长非递增子序列.
解决思路:
设X={x1,x2,…,xn}为依次飞来的导弹序列,Y={y1,y2,…,yk}为问题的最优解(即X的最长非递增子序列),s为问题的状态(表示导弹拦截系统当前发送炮弹能够到达的最大高度,初值为s=∞——第一发炮弹能够到达任意的高度).如果y1=x1,即飞来的第一枚导弹被成功拦截.那么,根据题意"
每一发炮弹都不能高于前一发的高度"
问题的状态将由s=∞变成s≤x1(x1为第一枚导弹的高度);
在当前状态下,序列Y1={y2,…,yk}也应该是序列X1={x2,…,xn}的最长非递增子序列(用反证法很容易证明).也就是说,在当前状态s≤x1下,问题的最优解Y所包含的子问题(序列X1)的解(序列Y1)也是最优的.这就是拦截导弹问题的最优子结构性质.
根据最优子结构性质推出状态转移方程:
设D(i)为第i枚导弹被拦截之后,这套系统最多还能拦截的导弹数(包含被拦截的第i枚).我们可以设想,当系统拦截了第k枚导弹xk,而xk又是序列X={xk,…,xn}中的最小值,即第k枚导弹之后飞来的导弹高度都比它高,则有D(k)=1;
当系统拦截了最后一枚导弹xn,那么,系统最多也只能拦截这一枚导弹了,即D(n)=1;
其它情况下,也应该有D(i)≥1.根据以上分析,可归纳出问题的动态规划递归方程为:
假设系统最多能拦截的导弹数为dmax(即问题的最优值),则
dmax(i为被系统拦截的第一枚导弹的顺序号)
所以,要计算问题的最优值dmax,需要分别计算出D
(1),D
(2),……D(n)的值,然后将它们进行比较,找出其中的最大值.即:
dmax=max{D(i)}(1<
=i且i<
=n)
分析子问题重叠,解决冗余
根据上面分析出来的递归方程,我们完全可以设计一个递归函数,采用自顶向下的方法计算D(i)的值.然后,对i从1到n分别调用这个递归函数,就可以计算出D
(1),D
(2),……D(n).程序如下:
intD(inti)
{
intj,max=0;
if((i==n)||(min(x,i,n)==x[i]))
//min(x,i,n)返回数组x在下标i—n之间的最小值
return1;
else
{
for(j=i+1;
j<
=n;
j++)
if(x[j]<
=x[i])
if(D(j)+1>
max)
max=D(j)+1;
returnmax;
}
}
从这个程序的递归模型中可以看出,会有大量的子问题被重复计算.比如在调用递归函数计算D
(1)的时候,可能需要先计算D(5)的值;
之后在分别调用递归函数计算D
(2),D(3),D(4)的时候,都有可能需要先计算D(5)的值.如此一来,在整个问题的求解过程中,D(5)可能会被重复计算很多次,从而造成了冗余,降低了程序的效率.
其实,通过以上分析,我们已经知道:
D(n)=1.如果将n作为阶段对问题进行划分,根据问题的动态规划递归方程,我们可以采用自底向上的方法依次计算出D(n-1),D(n-2),……D
(1)的值.这样,每个D(i)的值只计算一次,并在计算的同时把计算结果保存下来,程序如下:
voidD()
inti,j;
for(i=1;
i<
i++)
d(i)=1
for(i=n-1;
i>
=1;
i--)
if(x(j)<
=x(i)&
&
d(i)=d(j)+1>
dmax)
dmax=d(i);
xh=i;
}
由此我们出了最大拦截数的第一枚导弹的顺序号xh,即d(xh)为问题的解从而避免了有些子问题被重复计算的情况发生,提高了程序的效率.
在实际应用中,许多问题的阶段划分并不明显,这时如果刻意地划分阶段反而麻烦。
一般来说,只要该问题可以划分成规模更小的子问题,并且原问题的最优解中包含了子问题的最优解(即满足最优子化原理),则可以考虑用动态规划解决,也就是分治算法的思想。
例2:
传球游戏(NOIP2008普及组第三题)
【问题描述】
上体育课的时候,小蛮的老师经常带着同学们一起做游戏。
这次,老师带着同学们一起做传球游戏。
游戏规则是这样的:
n个同学站成一个圆圈,其中的一个同学手里拿着一个球,当老师吹哨子时开始传球,每个同学可以把球传给自己左右的两个同学中的一个(左右任意),当老师再次吹哨子时,传球停止,此时,拿着球没传出去的那个同学就是败者,要给大家表演一个节目。
聪明的小蛮提出一个有趣的问题:
有多少种不同的传球方法可以使得从小蛮手里开始传的球,传了m次以后,又回到小蛮手里。
两种传球的方法被视作不同的方法,当且仅当这两种方法中,接到球的同学按接球顺序组成的序列是不同的。
比如有3个同学1号、2号、3号,并假设小蛮为1号,球传了3次回到小蛮手里的方式有1->
2->
3->
1和1->
1,共2种。
【输入】
输入文件ball.in共一行,有两个用空格隔开的整数n,m(3<
=n<
=30,1<
=m<
=30)。
【输出】
输出文件ball.out共一行,有一个整数,表示符合题意的方法数。
【输入输出样例】
ball.in
33
ball.out
2
【限制】
40%的数据满足:
3<
=20
100%的数据满足:
=30
给n个同学从1—n编号,设状态F[p,t]表示传了t次球后,球在p手中,在剩下的m-t次传球中共有多少种方案到达1,由于在问题的求解中,球是从1号开始传,并最后回到1号,显然我们所求的目标状态就是是F[1,0]。
由于球只能传递给左右的两个同学,也只能通过左右的两个同学传递给自己,如下图:
由此,我们分析出F[1,0]的解只与F[1,1]和F[n,1]有关,而F[1,1]和F[n,1]也是最优问题解,因此,该问题符合最优子结构性质。
根据最优性原理我们可以得到以下状态转移方程:
通过以上分析,根据状态转移方程,运用记忆化搜索策略,采用自顶向下的过程可递归求出F[1,0],程序如下:
#include<
stdio.h>
stdlib.h>
#definemaxn31//最大人数,编号从1……n
#definemaxm30//最大传球次数
longf[maxn][maxm];
//表示传了T次球以后球在P号手里,包括在剩下的M-T次传球中有多少种方法走到1
longm,n;
voidfind(longp,longt)
if(t==m)//传了M次球了
if(p==1)//传到了1
f[p][t]=1;
else//没传到1
f[p][t]=0;
return;
}
if(f[p][t]!
=-1)return;
//如果这个状态搜到过了,没必要再搜
//标记该状态被搜过了
find(p%n+1,t+1);
//搜把球传给P右边的同学的状态
f[p][t]+=f[p%n+1][t+1];
intp1=p-1;
if(p1==0)p1=n;
find(p1,t+1);
//搜把球传给P左边的同学的状态
f[p][t]+=f[p1][t+1];
main()
//一开始所有状态都没到过
for(i=0;
maxn;
for(j=0;
maxm;
f[i][j]=-1;
scanf("
%d%d"
&
n,&
m);
find(1,0);
printf("
%ld"
f[1][0]);
代入数据测算
input:
33
数据模型如下:
:
可以从记忆数组中直接获取;
:
需搜索记忆的状态;
由于采用了记忆化搜索,处于不同位置的相同状态不会被多次搜索,因此可以在O(m×
n)的时间复杂度内完成任务,同样避免了子问题被重复计算的情况。
由此可知,动态规划法与分治法和贪心法类似,它们都是将问题实例归纳为更小的、相似的子问题,并通过求解子问题产生一个全局最优解。
贪心法:
当前选择可能要依赖已经作出的所有选择,但不依赖于有待于做出的选择和子问题。
因此贪心法自顶向下,一步一步地作出贪心选择;
分治法:
各个子问题是独立的(即不包含公共的子子问题),因此一旦递归地求出各子问题的解后,便可自下而上地将子问题的解合并成问题的解。
但不足的是,如果各子问题是不独立的,则分治法要做许多不必要的工作,重复地解公共的子问题。
动态规划:
利用分治思想把问题划分成规模更小的子问题,并且原问题的最优解中包含了子问题的最优解;
动态规划允许这些子问题不独立,(亦即各子问题可包含公共的子子问题)也允许其通过自身子问题的解作出选择,该方法对每一个子问题只解一次,并将结果保存起来,避免每次碰到时都要重复计算,从而解决解决冗余
因此,动态规划法所针对的问题有一个显著的特征,即它所对应的子问题树中的子问题呈现大量的重复。
动态规划法的关键就在于,对于重复出现的子问题,只在第一次遇到时加以求解,并把答案保存起来,让以后再遇到时直接引用,不必重新求解。
总结:
任何思想方法都有一定的局限性,超出了特定条件,它就失去了作用。
同样,动态规划也并不是万能的。
适用动态规划的问题必须满足最优化子结构性质。
特点:
1.以长远利益为目标的一些列决策,一般用来求解最优的问题解
2.符合最优化原理,可归结为一个递推式
3.也成为多阶段规划,特点体现在多阶段性
4.
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 动态 规划 入门 论文 设计