创作来自
[ACM_动态规划] UVA 12511 Virus [最长公共递增子序列 LCIS 动态规划]
首先是LCS,即最长公共子序列问题。
给定两个字符串s1s2...sn和t1t2...tn。求出两个字符串最长的公共子序列的长度。(字符串可以是数字)
定义dp数组。
dp[i][j]表示s1s2...si和t1t2...tj对应的LCS长度
由此,s1...s(i+1)和t1...t(j+1)对应的公共子序列可能是:
当s(i+1) = t(j+1)时,在s1s2...si和t1t2...tj的公共子序列末尾追加上s(i+1)
s1s2...si和t1t2...t(j+1)的公共子序列
s1s2...s(i+1)和t1t2...tj的公共子序列
三者中的某一个。
递推关系:
dp[i+1][j+1] =
max(dp[i][j]+1,dp[i][j+1],dp[i+1][j])(Si+1 = Tj+1)
max(dp[i][j+1],dp[i+1][j])
下面是模板,请勿生吃:!(来自《挑战程序设计竞赛》)
//输入
int n,m;
char s[maxn],t[maxn];
int dp[maxn+1][maxn+1];//DP数组
void solve(){
for(int i=0;i<n;i++){
for(int j=0;j<m;j++){
if(s[i]==t[i]){
dp[i+1][j+1] = dp[i][j]+1;
}else{
dp[i+1][j+1] = max(dp[i][j+1],dp[i+1][j]);
}
}
}
cout<<dp[n][m]<<endl;
}
其次是LIS,即最长上升子序列问题。
长为n的数列,a0,a1,...,an-1。求出这个序列中最长的上升子序列的长度。(满足任意i<j,ai<aj的序列)
定义dp数组:
dp[i]是以ai为末尾的最长上升子序列的长度
递推关系:
dp[i] = max{1,dp[j]+1|j<i且aj<ai}
可以在O(n2)时间内解决问题。
模板如下:
//输入
int n;
int a[maxn];
int dp[maxn];//DP数组
void solve(){
int res = 0;
for(int i=0;i<n;i++){
dp[i] = 1;
for(int j=0;j<i;j++){
if(a[j]<a[i]){
dp[i] = max(dp[i],dp[j]+1);
}
}
res = max(res,dp[i]);
}
cout<<res<<endl;
}
最后是。。LCIS。。
其实最终我还是不能够太理解这个做法,看还是看懂了,,但是感觉自己肯定写不出来,希望大神能够指点指点,可以让我完全领悟
定义dp数组。。
dp[i][j]表示以a串前i个字符b串的前j个字符且以b[j]为结尾构成的LCIS的长度
当a[i+1]!=b[j+1]时:dp[i+1][j]=dp[i][j]
当a[i+1]==b[j+1]时:dp[i+1][j]=max(dp[i][k])+1 1<=k<=j-1 && b[j]>b[k]
(代码中的i和解释中的i差了一位~~)
代码如下:
这是湖南第八届省赛的一道题,可以直接过的#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> using namespace std; const int maxn = 1005; int a[maxn]; int b[maxn]; int dp[maxn][maxn]; int main() { int t; cin>>t; while(t--) { memset(a,0,sizeof(a)); memset(b,0,sizeof(b)); int x,y; cin>>x; for(int i=1; i<=x; i++) cin>>a[i]; cin>>y; for(int i=1; i<=y; i++) cin>>b[i]; int res = 0; memset(dp,0,sizeof(dp)); for(int i=1; i<=x; i++) { int sum = 0; for(int j=1; j<=y; j++) { dp[i][j] = dp[i-1][j]; if(a[i]>b[j]&&sum<dp[i-1][j]) sum = dp[i-1][j]; if(a[i] == b[j]) dp[i][j] = sum + 1; } } for(int i=1; i<=y; i++) { if(res<dp[x][i]) { res = dp[x][i]; } } cout<<res<<endl; } }
https://vjudge.net/contest/161005#problem/J
这道题可以优化dp数组,变成一维因为每次i都是从上一行的结论得到的。。。
希望得到大神的指点。。。。