首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > 编程 >

动态规划范例篇

2012-11-01 
动态规划实例篇动态规划思想:把问题规模不断缩小成小问题,并求解出小问题的结果,然后返回最优结果。动态规

动态规划实例篇
动态规划思想:
把问题规模不断缩小成小问题,并求解出小问题的结果,然后返回最优结果。
动态规划必须满足最优化原理和无后效性。
什么叫做最优化原理(最优子结构性质):
简而言之,一个最优化策略的子策略总是最优的。一个问题满足最优化原理又称其具有最优子结构性质。
额外增加知识:
动态规划和递归不一样,递归是没有记录,对于同一个问题,出现多少次,会计算多少次。而动态规划不一样,对于相同的问题,只会计算一次。

下面以求最长公共子序列(LCS)为例:
问题描述
一个给定序列的子序列是在该序列中删去若干元素后得到的序列(元素的相对位置还是保持不变)。确切地说,若给定序列X=<x1, x2,…, xm>,则另一序列Z=<z1, z2,…, zk>是X的子序列是指存在一个严格递增的下标序列 <i1, i2,…, ik>,使得对于所有j=1,2,…,k有

例如,序列Z=<B,C,D,B>是序列X=<A,B,C,B,D,A,B>的子序列,相应的递增下标序列为<2,3,5,7>。

给定两个序列X和Y,当另一序列Z既是X的子序列又是Y的子序列时,称Z是序列X和Y的公共子序列。例如,若X=<A, B, C, B, D, A, B>和Y=<B, D, C, A, B, A>,则序列<B, C, A>是X和Y的一个公共子序列,序列<B, C, B, A>也是X和Y的一个公共子序列。而且,后者是X和Y的一个最长公共子序列,因为X和Y没有长度大于4的公共子序列。

最长公共子序列(LCS)问题:给定两个序列X=<x1, x2, …, xm>和Y=<y1, y2, … , yn>,要求找出X和Y的一个最长公共子序列。

解答
首先,要证明LCS是否有最优子结构性质。
设序列X=<x1, x2, …, xm>和Y=<y1, y2, …, yn>的一个最长公共子序列Z=<z1, z2, …, zk>,则:

(1)若xm=yn,则zk=xm=yn且Zk-1是Xm-1和Yn-1的最长公共子序列;
(2)若xm≠yn且zk≠xm ,则Z是Xm-1和Y的最长公共子序列;
(3)若xm≠yn且zk≠yn ,则Z是X和Yn-1的最长公共子序列。
其中Xm-1=<x1, x2, …, xm-1>,Yn-1=<y1, y2, …, yn-1>,Zk-1=<z1, z2, …, zk-1>。
在这里,重新描述一下。
问题对象(PO)是X=<x1, x2, …, xm>和Y=<y1, y2, …, yn>
把PO问题不断降低规模,也就是
x<1,m-1> y<1,n-1>
x<1,m-2> y<1,n-2>
x<1,m-3> y<1,n-3>
......
求出这一系列问题的值,选择最优值。
这个就是动态规划思想啦。
根据上面(1)、(2)、(3),可以看出是不断降低问题规模,求出问题最优(最长)值。
因此,最长公共子序列问题具有最优子结构性质。
由性质导出子问题的递归结构
当 i = 0 or j = 0 时 , c[i][j] = 0
当 i , j > 0 ; xi = yi 时 , c[i][j] = c[i-1][j-1] + 1
当 i , j > 0 ; xi != yi 时 , c[i][j] = max { c[i][j-1] , c[i-1][j] }
如图所示:



相关代码如下:

        int[][] b = new int[x.length][y.length];  //记录c[i][j]是通过哪一个子问题的值求得的        int[][] c = new int[x.length][y.length]; //记录X[i]与Y[j] 的LCS 的长度        for(int i = 0; i < x.length; i++)            c[i][0] = 0;        for(int j = 1; j < y.length; j++)            c[0][j] = 0;        for(int i=1; i<x.length; i++)          {              for(int j=1; j<y.length; j++)             {                  if( x[i] == y[j])                  {                      c[i][j] = c[i-1][j-1] + 1;                      b[i][j] = 1;                  }                  else if(c[i-1][j] >= c[i][j-1])                  {                      c[i][j] = c[i-1][j];                      b[i][j] = 0;                  }                  else                  {                      c[i][j] = c[i][j-1];                      b[i][j] = -1;                  }              }          }     

具体的LCS实现,请看这里
http://lzj0470.iteye.com/blog/1135649

热点排行