作者提示:本文改编自动态规划概念和实例讲解 - 算法竞赛教程 - C语言网,更加详细,版权归Dotcpp编程(C语言网) 所有
动态规划算法是常用的算法之一,通常用于求解具有某种最优性质的问题。
动态规划主要用于求解以时间划分阶段的动态过程的优化问题,动态规划程序设计是对解最优化问题的一种途径、一种方法,而不是一种特殊算法。它往往是针对一种最优化问题,由于各种问题的性质不同,确定最优解的条件也互不相同,因而动态规划的设计方法对不同的问题,有各具特色的解题方法,而不存在一种万能的动态规划算法,可以解决各类最优化问题。
动态规划算法的设计主要有两种方法:
(1)从上到下(记忆化搜索):基本上对应着递归函数实现,从大范围开始计算,要注意不断保存中间结果,避免重复计算
(2)从下到上(约等于递推):递推计算
动态规划在编程中常解决最长公共子序列问题:
给出两个字符串A B,求A与B的最长公共子序列(子序列不要求是连续的)。
比如两个串为:abcba 和 abcab,则 ab是两个串的子序列,abc也是,abca也是,其中abca是这两个字符串最长的子序列。
思路:此题的切入点就是动态规划,通过动归来确定哪些字符是最长公共子序列中的字符表示第一个序列的前i个字符和第二个序列的前j个字符的公共子序列
代码如下:
#include<queue>
#include<cmath>
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#define INF 0x3f3f3f3f
using namespace std;
char a[1001], b[1001];
int dp[1001][1001], len1, len2;
void lcs(int i, int j)
{
for(i=1; i<=len1; i++)
{
for(j=1; j<=len2; j++)
{
if(a[i-1] == b[j-1])
dp[i][j] = dp[i-1][j-1] + 1;
else if(dp[i-1][j] > dp[i][j-1])
dp[i][j] = dp[i-1][j];
else
dp[i][j] = dp[i][j-1];
}
}
}
void llcs()
{
int i, j, z = 0;
char c[1001];
memset(c, 0, sizeof(c));
i = len1, j = len2;
while(i!=0 && j!=0)
{
if(a[i-1] == b[j-1])
{
c[z++] = a[--i];
j--;
}
else if(dp[i-1][j] < dp[i][j-1])
j--;
else if(dp[i][j-1] <= dp[i-1][j])
i--;
}
for(i=z-1; i>=0; i--)
printf("%c", c[i]);
printf("\n");
}
int main()
{
while(~scanf(" %s", a))
{
scanf(" %s", b);
memset(dp, 0, sizeof(dp));
len1 = strlen(a);
len2 = strlen(b);
lcs(len1, len2);
llcs();
}
return 0;
}
遍历两个数组,如果两个是一样的,这个位置的最大值就是dp数组左上角
否则就是dp左面(i-1)和上面(j-1)的最大值
理解就评论+关注