Codeforces Round #358 (Div. 2) DP
http://www.codeforces.com/problemset/problem/682/D
题意:最长公子序列,限制是最多分成k段,也就是你得到的最长公子序列不能实在原串中分成K段以上。
思路:一个DP。。想了很久。。果然DP始终没法入门。。我们设状态是DP[ i ] [ j ] [ k ] [ s ] 表示匹配到第i,j时分成k段,此时是连续或不连续时的最长LCS。。
类比LCS的转移方法。。最关键的就是最后一个状态S的处理。。。
s[i] != t[j] 时。。显然 DP【x】【y】【z】【0】的转移和普通的LCS没什么区别,因为当前位置都不匹配,所以DP【x】【y】【z】【1】显然是0了。。
当 s[i] == t[j]时。。显然不连续的部分转移依旧很简单没什么好说的。。连续的时候就要注意了。。首先他可能从k-1来也可能从k来,从k-1来的话那有必然从【k-1】【0】来。。这么说的话思路就很清晰了。。于是愉快的水过去。。。
代码:
#include <bits/stdc++.h>
using namespace std;
const int maxn=1001;
char s[maxn];
char t[maxn];
int dp[maxn][maxn][11][2];
int main(){
    int n,m,lim;
    scanf("%d%d%d",&n,&m,&lim);
    scanf("%s%s",s,t);
    for(int i=0;i<n;i++){
        for(int j=0;j<m;j++){
            for(int k=1;k<=lim;k++){
                if(s[i]==t[j]){
                    int a,b;
                    a=dp[i][j][k][1]+1;
                    b=max(dp[i][j+1][k-1][0],max(dp[i+1][j][k-1][0],dp[i][j][k-1][0]+1));
                    dp[i+1][j+1][k][1]=max(a,b);
                    a=max(dp[i][j+1][k][1],dp[i+1][j][k][1]);
                    b=max(dp[i][j+1][k][0],dp[i+1][j][k][0]);
                    dp[i+1][j+1][k][0]=max(a,b);
                }
                else{
                    int a,b;
                    a=max(dp[i][j+1][k][1],dp[i+1][j][k][1]);
                    b=max(dp[i][j+1][k][0],dp[i+1][j][k][0]);
                    dp[i+1][j+1][k][0]=max(a,b);
                    dp[i+1][j+1][k][1]=0;
                }
            }
        }
    }
    int ans=0;
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
            for(int k=1;k<=lim;k++){
                ans=max(ans,max(dp[i][j][k][0],dp[i][j][k][1]));
            }
        }
    }
    printf("%d\n",ans);
}
 
            


                
            
        
浙公网安备 33010602011771号