动态规划算法步骤-Read_第1页
动态规划算法步骤-Read_第2页
动态规划算法步骤-Read_第3页
动态规划算法步骤-Read_第4页
动态规划算法步骤-Read_第5页
已阅读5页,还剩34页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

本讲稿主要来源福州大学数学与计算机科学学院第一节

动态规划的基本要素

动态规划主要用于组合优化问题,即求一个离散问题在某种意义下的最优解,有时也用于组合计数问题。那么,什么样的问题适合用动态规划求解呢?适合用动态规划求解的问题的两个基本要素:

(1)最优子结构性质一个问题可用动态规划有效求解的基本要求是该问题具有最优子结构性质,通俗地讲即问题的最优解包含其子问题的最优解。

(2)子问题重叠性质

动态规划所针对的问题还有另外一个显著的特征,即它所对应的子问题树中的子问题呈现大量的重复,称为子问题重叠性质。在应用动态规划时,对于重复出现的子问题,只需在第一次遇到时加以求解,并把答案保存起来,以便以后再遇到时直接引用,不必重新求解,从而大大地提高解题的效率。相比之下,一般的搜索技术,对于某个子问题,不管是否已经求解过,只要遇上,就会再次对它求解,因而影响了解题的效率。实例一、数字三角形问题

1.问题描述给定一个具有N层的数字三角形,从顶至底有多条路径,每一步可沿左斜线向下或沿右斜线向下,路径所经过的数字之和为路径得分,请求出最小路径得分。

2621841568图4—1数字三角形

2.解题思路这道题可以用动态规划成功地解决,但是,如果对问题的最优结构刻画得不恰当(即状态表示不合适),则无法使用动态规划。状态表示法一:用一元组D(X)描述问题,D(X)表示从顶层到达第X层的最小路径得分。因此,此问题就是求出D(N)(若需要,还应求出最优路径)。这是一种很自然的想法和表示方法。遗憾的是,这种描述方式并不能满足最优子结构性质。因为D(X)的最优解(即最优路径)可能不包含子问题例如D(X-1)的最优解。如图4—1所示:显然,D(4)=2+6+1+1=10,其最优解(路径)为2-6-1-1。而D(3)=2+2+4=8,最优解(路径)为2-2-4。故D(4)的最优解不包含子问题D(3)的最优解。由于不满足最优子结构性质,因而无法建立子问题最优值之间的递归关系,也即无法使用动态规划。

2621841568图4—1数字三角形

状态表示法二:用二元组D(X,y)描述问题,D(X,y)表示从顶层到达第X层第y个位置的最小路径得分。最优子结构性质:容易看出,D(X,y)的最优路径Path(X,y)一定包含子问题D(X-1,y)或D(X-1,y-1)的最优路径。否则,取D(X-1,y)和D(X-l,y-1)的最优路径中得分小的那条路径加上第X层第y个位置构成的路径得分必然小于Path(X,y)的得分,这与Path(X,y)的最优性是矛盾的。

2621841568图4—1数字三角形

如图4—1所示,D(4,2)的最优路径为2-6-1-5,它包含D(3,1)最优路径2-6-1。因此,用二元组D(X,y)描述的计算D(X,y)的问题具有最优子结构性质。递归关系:

D(X,y)=min{D(X-1,y),D(X-1,y-1}+a(X,y)D(1,1)=a(1,1)其中,a(X,y)为第X层第y个位置的数值。原问题的最小路径得分可以通过比较D(N,i)获得,其中i=1,2,…,N。在上述递归关系中,求D(X,y)的时候,先计算D(X-1,y)和D(X-1,y-1),下一步求D(X,y+1)时需要D(X-1,y+1)和D(X-1,y),但其中D(X-1,y)在前面已经计算过了。于是,子问题重叠性质成立。因此,采用状态表示法二描述的问题具备了用动态规划求解的基本要素,可以用动态规划进行求解。状态表示法三:采用状态表示法二的方法是从顶层开始,逐步向下至底层来求出原问题的解。事实上,还可以从相反的方向考虑。仍用二元组D(X,y)描述问题,D(X,y)表示从第X层第y个位置到达底层的最小路径得分。原问题的最小路径得分即为D(1,1)。最优子结构性质:显然,D(X,y)的最优路径Path(X,y)一定包含子问题D(X+1,y)或D(X+1,y+1)的最优路径,否则,取D(X+1,y)和D(X+1,y+1)的最优路径中得分小的那条路径加上第X层第y个位置构成的路径得分必然小于Path(X,y)的得分,这与Path(X,y)的最优性矛盾。

2621841568图4—1数字三角形

如图所示,D(1,1)的最优路径为2-6-1-1,它包含D(2,1)的最优路径6-1-1。因此,这种状态表示描述的计算D(X,y)的问题同样具有最优子结构性质。递归关系:

D(X,y)=min{D(X+1,y),D(X+1,y+1)}+a(X,y)D(N,k)=a(N,k),k=1,…,N其中,a(X,y)为第X层第y个位置的数值。

D(X,y)表示从第X层第y个位置到达底层的最小路径得分。原问题的最小路径得分即为D(1,1)。算法设计

采用状态表示法三的算法的主要过程如下:for(i=n-2;i>=0;--i){ for(j=0;j<=i;++j) { tmp=sou[i+1][j]; if(sou[i+1][j+1]<tmp) { tmp=sou[i+1][j+1]; } sou[i][j]+=tmp; }}printf("%d\n",sou[0][0]);第二节

动态规划算法步骤

(1)选择适当的问题状态表示,并分析最优解的性质;(2)递归地定义最优值(即建立递归关系);(3)以自底向上的方式计算出最优值;

(4)根据计算最优值时得到的信息,构造一个最优解。

步骤(1)~(3)是动态规划的基本步骤。在只需要求出最优值的情形,步骤(4)可以省略。若需要求出问题的一个最优解,则必须执行步骤(4)。此时,在步骤(3)中计算

最优值时,通常需记录更多的信息,以便在步骤(4)中,根据所记录的信息,快速地构造出一个最优解。注意事项:

在进一步探讨动态规划设计方法及应用之前,有两点需要注意:

(1)问题的状态表示对能否用动态规划进行求解是至关重要的,不恰当的状态表示将使问题的描述不具有最优子结构性质,从而无法建立最优值的递归关系,动态规划的应用也就无从谈起。因此,上面步骤(1),即状态表示和最优子结构性质的分析,是最关键的一步。

(2)在算法的程序设计中,应充分利用子问题重叠性质来提高解题效率。更具体地说,应采用递推(迭代)的方法来编程计算由递归式定义的最优值,而不采用直接递归的方法。实例二、花束摆放问题

1.问题描述现在有F束不同品种的花束,同时有至少同样数量的花瓶被按顺序摆成一行,其位置固定于架子上,并从1至V按从左到右顺序编号,V是花瓶的数目(F≤V)。花束可以移动,并且每束花用1至F的整数唯一标识。标识花束的整数决定了花束在花瓶中排列的顺序,如果i<j,花束i必须放在花束j左边的花瓶中。每个花瓶只能放一束花。如果花瓶的数目大于花束的数目,则多余的花瓶空置。

每一个花瓶都具有各自的特点。因此,当各个花瓶中放入不同的花束时,会产生不同的美学效果,并以一美学值(一个整数)来表示,空置花瓶的美学值为零。为取得最佳美学效果,必须在保持花束顺序的前提下,使花束的摆放取得最大的美学值。请求出具有最大美学值的一种摆放方式。2.解题思路状态表示法一:设A(i,j)表示第i种花束摆在第j个花瓶中获得的美学值。S(i,k)表示第i种花束摆在第k个花瓶中时(这里k≥i),前i种花束能够获得的最大美学值(之和)。这样,原问题的最优值可以通过计算max{S(F,k)

F≤k≤V}获得。下面要分析一下这种状态表示法描述问题的方式是否具备了用动态规划求解的基本要素。

最优子结构性质:对满足F≤k≤V的k,设T(F,k)是达到最优值S(F,k)的一种最佳摆放方式,其中,第F-1种花束摆在第j个花瓶中(j<k),则T(F,k)中前F-1种花束的摆放方式获得的美学值为S(F-1,j)。故对每个满足F≤k≤V的k,计算S(F,k)的问题具有最优子结构性质。

递归方程:S(i,k)=max{S(i-1,j)

i-1≤j≤k-1}+A(i,k),i>1S(1,k)=A(1,k)在计算S(i,k-1)时,已经计算出了S(i-1,j),i-1≤j≤k-2及其max{S(i-1,j)

i-1≤j≤k-2}。因此,计算S(i,k)时,只要将S(i-1,k-1)与max{S(i-1,j)

i-1≤j≤k-2}进行比较即可求得,即子问题重叠性质。这样做可以大大减少计算量。事实上,还可以有更直接的方法。

状态表示法二:

设S[i,k]表示第i种花束摆在第k个之前(包括第k个)的任意某个花瓶中,前i种花束能够获得的最大美学值(之和)。这样,原问题的最优值即为S[F,V]。这比前一个表示法更直接。

容易验证,计算S[F,V]的问题具有最优子结构性质。其递归方程为:

S[i,k]=max{S[i-1,k-1]+A(i,k),S[i,k-1]},(i>1,k>i);

初始条件为:S[1,1]=A[1,1];S[1,k]=max{A(1,k),S[1,k-1]},(k>1);S[i,i]=S[i-1,i-1]+A(i,i),(i>1)

算法设计(状态表示法二)算法的过程如下:

s[0][0]=a[0][0];out[0][0]=true;for(j=1;j<v;++j){ s[0][j]=s[0][j-1]>a[0][j]?s[0][j-1]:a[0][j]; out[0][j]=(s[0][j]!=s[0][j-1]); for(i=1;i<f&&i<j;++i) { s[i][j]=s[i][j-1]; s[i][j]>?=s[i-1][j-1]+a[i][j]; out[i][j]=(s[i][j]!=s[i][j-1]); } s[i][j]=s[i-1][j-1]+a[i][j];out[i][j]=true; if(i<j) { s[i][j]>?=s[i][j-1];out[i][j]=(s[i][j]!=s[i][j-1]); }}实例三显然可以在数串读入以后用搜索的方法找出这个最大子串!也很显然那样很麻烦!怎么办呢?考虑每输入一个数的时候便做记录,那样等数串读入完毕的时候,最大子串和到底是多少也就知道了!这算动态规划的一个引申!以第一例为例:-3492-10-7113-8记录方法:-3413155-711146把当前的最大和(含当前末尾的最大和)记录下来,虽然不能直接得出最大和是多少,但可以进行遍历搜索最大值即可!关键是要对负数处理好,看例二,最大子串含有负数。-126-35-714-5-1518-49-128?如果在此处断开记录-3,那么前面的2,6两个正数就和后边断开了,实际上2+6+(-3)>0,如果后边是正数的话,完全可以加上这3个数(比如后边的5)-128510?相同处理:-12851031712?后面是-15,加上12(前面的子串能形成的最大和)也小于0,所以此处应该断开了!记录-15!最后-12851031712-1518413!!!还有一点,如果输入全为非正数的话,那么最大子串就是最大的那个数了!伪代码:输入数组a[i],用数组s[i]记录当前最大子串和,num记录最大值。for(i=0;i<n;i++){输入a[i];s[0]=a[0];num记录当前最大的数;}if(num<=0)最大就为num!for(i=1;i<n;i++){if(s[i-1]>=0)s[i]=s[i-1]+a[i];elses[i]=a[i];num=(num<b[i])?b[i]:num;}实例四NKOJ1339Subsquence题目描述:给定一个数串和一个数S,在数串中找出大于等于S的一个连续子列!且该子列是满足上述条件的最短子列!数串数字个数N:10<N<100000,每个数小于10000。比如:101551351074928最短为2;51112345最短为3。该题简单分析:题意知所有数

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论