动态规划 _DP.ppt

  1. 1、本文档共44页,可阅读全部内容。
  2. 2、原创力文档(book118)网站文档一经付费(服务费),不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。
  3. 3、本站所有内容均由合作方或网友上传,本站不对文档的完整性、权威性及其观点立场正确性做任何保证或承诺!文档内容仅供研究参考,付费前请自行鉴别。如您付费,意味着您自己接受本站规则且自行承担风险,本站不退款、不进行额外附加服务;查看《如何避免下载的几个坑》。如果您已付费下载过本站文档,您可以点击 这里二次下载
  4. 4、如文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“版权申诉”(推荐),也可以打举报电话:400-050-0827(电话支持时间:9:00-18:30)。
查看更多
动态规划 _DP

动态规划 Dynamic Programming 唐陈兴 2007.12.30 动态规划的基本思想 动态规划算法通常用于求解具有某种最优性质的问题。在这类问题中,可能会有许多可行解。每一个解都对应于一个值,我们希望找到具有最优值的解。动态规划算法与分治法类似,其基本思想也是将待求解问题分解成若干个子问题,先求解子问题,然后从这些子问题的解得到原问题的解。与分治法不同的是,适合于用动态规划求解的问题,经分解得到子问题往往不是互相独立的。若用分治法来解这类问题,则分解得到的子问题数目太多,有些子问题被重复计算了很多次。 如果我们能够保存已解决的子问题的答案,而在需要时再找出已求得的答案,这样就可以避免大量的重复计算,节省时间。我们可以用一个表来记录所有已解的子问题的答案。不管该子问题以后是否被用到,只要它被计算过,就将其结果填入表中。这就是动态规划法的基本思路。具体的动态规划算法多种多样,但它们具有相同的填表格式。 动态规划法一般步骤 1、找出最优解的性质,并刻画其结构特征; 2、递归地定义最优值(写出动态规划方程); 3、以自底向上的方式计算出最优值; 4、根据计算最优值时得到的信息,构造一个最优解。 步骤1-3是动态规划算法的基本步骤。在只需要求出最优值的情形,步骤4可以省略,步骤3中记录的信息也较少;若需要求出问题的一个最优解,则必须执行步骤4,步骤3中记录的信息必须足够多以便构造最优解。 动态规划问题的特征 动态规划算法的有效性依赖于问题本身所具有的两个重要性质:最优子结构性质和子问题重叠性质。 1、最优子结构:当问题的最优解包含了其子问题的最优解时,称该问题具有最优子结构性质。 2、重叠子问题:在用递归算法自顶向下解问题时,每次产生的子问题并不总是新问题,有些子问题被反复计算多次。动态规划算法正是利用了这种子问题的重叠性质,对每一个子问题只解一次,而后将其解保存在一个表格中,在以后尽可能多地利用这些子问题的解。 从一个简单的问题入手 FOJ1004 Number Triangle 求人从顶端到底部,每次只能向左下右下走,最多能取得的值. 从一个简单的问题入手 状态表示 用a[i][j]表示第i行第j列的值。 用F(i,j)表示第i行第j列走到底部所能取得的最大值。而F(1,1)就是题目所求的答案。 搜索源代码 #includecstdio const int M=1000+5; int a[M][M],n; inline int max(int x,int y){ return xy?y:x; } int f(int i,int j){ if (i==n) return a[i][j]; else return a[i][j]+max(f(i+1,j),f(i+1,j+1)); } int main(){ int i,j; while(scanf(%d,n)==1){ for(i=1;i=n;i++) for(j=1;j=i;j++) scanf(%d,a[i][j]); printf(%d\n,f(1,1)); } return 0; } 从一个简单的问题入手 人每次从顶部往下走,都有2种选择。 如果搜索,到第n层的搜索量为为2n。 1=n=1000,这种搜索量是从时间角度无法接受的。 细心观察,不难发现实际上做了很多重复的搜索。 用动态规划思想解决 减少重复计算:自底向上。 状态表示 用a[i][j]表示第i行第j列的值。 用F[i][j]表示第i行第j列走到底部所能取得的最大值。而F[1][1]就是题目所求的答案。 状态转移 F[i][j]=a[i][j]+max(F[i+1][j],F[i+1][j+1]) 动态规划源代码 #includecstdio const int M=1000+5; int f[M][M],a[M][M]; inline int max(int x,int y){ return xy?y:x; } int main(){ int i,j,n; while(scanf(%d,n)==1){ for(i=1;i=n;i++) for(j=1;j=i;j++) scanf(%d,a[i][j]); for(j=1;j=n;j++) f[n][j]=a[n][j]; for(i=n-1;i=1;i--) for(j=1;j=i

文档评论(0)

zw4044 + 关注
实名认证
内容提供者

该用户很懒,什么也没介绍

1亿VIP精品文档

相关文档