动态规划(dynamic programming)是通过组合子问题的解而解决整个问题的,这里的programming是一种规划,DP适用于子问题不是独立(俩个子问题不共享资源即是独立)的问题,即各个子问题包含公共子问题,DP只对于子问题求解一次,并将求解的值保存在一张表中,避免了重复求解相同子问题的操作。DP通常用于最优化的问题,通常是一个问题有很多的可行解,每一个解含有一个值,我们希望找到一个最优的解(最大或是最小)。
DP一般设计的4个步骤:
1.描述最优解的结构
2.递归定义最优解的值
3.按照自底向上的方式求解最优解的值
4.有计算结果构造最优解
DP性质:对于一个问题是否可以用DP解决是需要判断的,如果一个问题的最优解当中包含了子问题的最优解,即该问题具有最优子结构性质,提示我们用DP可能会解决问题。而当一个递归算法不断调用同一问题的时候,此时该最优问题包含了重叠子问题。同时满足二者,此时我们可以用DP去求解问题。
下面针对于一个简单的DP小例子进行描述:
数字三角形问题,问题描述:
对于输入一个数字三角形,每行的整数个数对应其行数,在三角形中需找一条从顶到底的路径,使得路径上的数字之和最大,输出最大值,三角形行数小于100,路径上的每一步只可以向下或右下去走。给出一个问题的样例:
求出上述例子的最大解?
分析:喎?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).
演示如下图:
即为所求解。
#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适用于子问题不是独立(俩个子问题...