java编程动态规划,动态规划 以及相应的实例

动态规划(dynamic programming)是通过组合子问题的解而解决整个问题的,这里的programming是一种规划,DP适用于子问题不是独立(俩个子问题不共享资源即是独立)的问题,即各个子问题包含公共子问题,DP只对于子问题求解一次,并将求解的值保存在一张表中,避免了重复求解相同子问题的操作。DP通常用于最优化的问题,通常是一个问题有很多的可行解,每一个解含有一个值,我们希望找到一个最优的解(最大或是最小)。

DP一般设计的4个步骤:

1.描述最优解的结构

2.递归定义最优解的值

3.按照自底向上的方式求解最优解的值

4.有计算结果构造最优解

DP性质:对于一个问题是否可以用DP解决是需要判断的,如果一个问题的最优解当中包含了子问题的最优解,即该问题具有最优子结构性质,提示我们用DP可能会解决问题。而当一个递归算法不断调用同一问题的时候,此时该最优问题包含了重叠子问题。同时满足二者,此时我们可以用DP去求解问题。

下面针对于一个简单的DP小例子进行描述:

数字三角形问题,问题描述:

对于输入一个数字三角形,每行的整数个数对应其行数,在三角形中需找一条从顶到底的路径,使得路径上的数字之和最大,输出最大值,三角形行数小于100,路径上的每一步只可以向下或右下去走。给出一个问题的样例:

c842e5f4fba97b52ca6f4833cf2da624.png

求出上述例子的最大解?

分析:喎?http://www.Bkjia.com/kf/ware/vc/" target="_blank" class="keylink">vcD4KPHA+yc/K9sr9vt2/ydLU08PSu7j2tv7OrMr91+m9+NDQw+jK9qOsvLQ8L3A+CjxwcmUgY2xhc3M9"brush:java;">D[i][j] 第i行第j个数 从D[i][j]下一步走D[i+1][j]或D[i+1][j+1] Max[i][j] 表示从D[i][j]到底端的路径中最佳路径数字之和。如果只有一行的时候 Max[i][j] = D[i][j],否则Max[i][j] = max(Max[i+1][j],Max[i+1][j+1])+D[i][j];

下面给出递推型DP:

#include #include

#include using namespace std;

const int num = 101;

int D[num][num];

int n;

int Max[num][num];

int main()

{

int i,j;

cin>>n;

for(i=1;i<=n;i++)

for(j=1;j<=i;j++)

cin>>D[i][j];

for(int k=1;k<=n;k++)

Max[n][k] = D[n][k];

for(int i=n-1;i>=1;i--){

for(int j=1;j<=i;j++)

Max[i][j] = max(Max[i+1][j],Max[i+1][j+1])+D[i][j];

}

cout

上述算法时间复杂度o(n^2),空间复杂度o(n^2),有图表可知,最后的有很大的内存空间是浪费的,并不会全部利用上,当行数很大的时候浪费明显,我们可以将计算出来的每个子问题的解存放在一个一维数组中,覆盖性的写入,从而最后的解即为数组的头元素。空间复杂度即为o(n).

演示如下图:

d7faab208d8e9457bd6b4227232b385e.png

a273621caa92fcfd582986579450037e.png即为所求解。

#include #include

#include using namespace std;

const int num = 101;

int D[num][num];

int n;

int *Max;

int main()

{

int i,j;

cin>>n;

for(i=1;i<=n;i++)

for(j=1;j<=i;j++)

cin>>D[i][j];

Max = D[n];

for(int i=n-1;i>=1;i--){

for(int j=1;j<=i;j++)

Max[j] = max(Max[j],Max[j+1])+D[i][j];

}

cout

俩个字符串s1,s2,用maxlen(i,j)表示s1左边i个字符,s2左边j个字符的最长公共子序列长度。(解的状态)

如果俩个子串任何一个为空,公共子串的长度为0;代码如下:

#include #include

#include #include char s1[100];

char s2[100];

int maxlen[100][100];

using namespace std;

int main()

{

while(cin>>s1>>s2){

int len1 = strlen(s1);

int len2 = strlen(s2);

int i,j;

for(i=0;i<=len1;i++)

maxlen[i][0] = 0;

for(j=0;j<=len2;j++)

maxlen[0][j] = 0;

for(i=1;i<=len1;i++){

for(j=1;j<=len2;j++){

if(s1[i-1]==s2[j-1])

maxlen[i][j] = maxlen[i-1][j-1]+1;

else

maxlen[i][j] = max(maxlen[i-1][j],maxlen[i][j-1]);

}

}

cout << maxlen[len1][len2] << endl;

}

return 0;

}最长公共子串并不要求,子串是连续的。

http://www.dengb.com/Javabc/777577.htmlwww.dengb.comtruehttp://www.dengb.com/Javabc/777577.htmlTechArticle动态规划(dynamic programming) 是通过组合子问题的解而解决整个问题的,这里的programming是一种规划,DP适用于子问题不是独立(俩个子问题...

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值