1.最长上升子序列
什么是最长上升子序列?就是从一排数据中,按顺序(不必连续)的选出最长的上升序列
用dp[i]表示以i为结尾的最长上升子序列。
状态方程dp[i] = max(dp[j] , 0) + 1
j满足小于i
例题1:http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=17613
题意:当另一个点的数值大于当前点时可以从一个点跳到另一个点,求最大的所有跳到的点的和
思路:dp[i]表示以i为结尾的最长上升子序列。初始化dp[i]为该数值本身。dp[i] = max(dp[j] + a[i],dp[i])
代码:
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
int a[1005];
int dp[1005];
int main()
{
//freopen("in.txt","r",stdin);
int n;
while(1){
scanf("%d",&n);
if(n == 0)
break;
for(int i = 0; i < n; i ++)
{
scanf("%d",& a[i]);
}
for(int i = 0; i < n; i ++)
{
dp[i] = a[i];
for(int j = 0; j < i; j ++)
{
if(a[i] > a[j])
{
dp[i] = max(dp[j] + a[i],dp[i]);
}
}
}
int maxn = 0;
for(int i = 0; i < n; i ++)
{
maxn = max(dp[i],maxn);
}
printf("%d\n",maxn);
}
return 0;
}
2.最长公共子序列
i,j分别为指向两个字符串的指针。当a[i] == a[j]时,dp[i][j] = dp[i - 1][j - 1] + 1
当a[i] != a[j]时,dp[i][j] = max(dp[i - 1][j],dp[i][j - 1])
注意对边界值的处理
例题二:http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=22149
题意:有多组,每组两个字符串,问最长公共子序列是多长
思路:简单套用
代码:
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
string s1,s2;
int dp[1005][1005];
int main()
{
//freopen("in.txt","r",stdin);
while(cin>>s1>>s2)
{
memset(dp,0,sizeof(dp));
int n = s1.size();
int m = s2.size();
for(int i = 0; i < n; i ++)
{
for(int j = 0; j < m; j ++)
{
if(s1[i] == s2[j])
{
if(i < 1 || j < 1)
dp[i][j] = 1;
else
dp[i][j] = dp[i - 1][j -1] + 1;
}
else
{
if(i < 1 && j < 1)
dp[i][j] = 0;
else if(i < 1 )
dp[i][j] = dp[i][j - 1];
else if(j < 1)
dp[i][j] = dp[i - 1][j];
else
dp[i][j] = max(dp[i -1][j],dp[i][j - 1]);
}
}
}
printf("%d\n",dp[n - 1][m - 1]);
}
return 0;
}