动态规划实例篇

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

下面以求最长公共子序列(LCS)为例:
[b]问题描述[/b]
一个给定序列的子序列是在该序列中删去若干元素后得到的序列(元素的相对位置还是保持不变)。确切地说,若给定序列X=<x1, x2,…, xm>,则另一序列Z=<z1, z2,…, zk>是X的子序列是指存在一个严格递增的下标序列 <i1, i2,…, ik>,使得对于所有j=1,2,…,k有
[img]http://dl.iteye.com/upload/attachment/526371/b5c2cab7-d6e2-36c9-a472-fc4a6b11a01c.gif[/img]
例如,序列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的一个最长公共子序列。

[b]解答[/b]
首先,要证明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),可以看出是不断降低问题规模,求出问题最优(最长)值。
[b]因此,最长公共子序列问题具有最优子结构性质。[/b]
由性质导出子问题的递归结构
当 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] }
如图所示:

[img]http://dl.iteye.com/upload/attachment/526513/316bfca4-4d05-3491-b6b6-b6e0f7373879.png[/img]

相关代码如下:

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
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

lzj0470

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值