LightOJ1013 Love Calculator(DP)

容易猜测到包含s1、s2序列的串的最短长度是LCS(s1,s2) + ( len(s1) - LCS(s1,s2) ) + ( len(s2) - LCS(s1,s2) ) ,即:

len(s1)+len(s2)-LCS(s1,s2)

接下来求方案数,可以想到:

dp[k][i][j]表示由s1前i位和s2前j位的序列构成的长度为k的串的方案数

dp[k][i][j]是由dp[k-1][i-1][j]、dp[k-1][i][j-1]和dp[k-1][i-1][j-1]转移的,而从dp[k-1][i-1][j-1]转移则要满足s1[i]==s2[j]的条件。

转移方程我纠结了好久,才“试”出来:

dp[k][i][j] = (s1[i]==s2[j]) ? dp[k-1][i-1][j-1] : dp[k-1][i-1][j]+dp[k-1][i][j-1]

然后因为自己想的一个数据s1="aa",s2="ab"又纠结了好久,才“试”出初始状态是:

d[1][1][0]=d[1][0][1]=1

(s1[1]==s2[1]) ? d[1][1][1]=1 : d[1][1][1]=0

最后提交就AC了,有点不明觉厉。。

 

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 using namespace std;
 5 int LCS[33][33];
 6 long long d[66][33][33];
 7 int main(){
 8     int t;
 9     char s1[33],s2[33];
10     scanf("%d",&t);
11     for(int cse=1; cse<=t; ++cse){
12         scanf("%s%s",s1+1,s2+1);
13 
14         int l1=strlen(s1+1),l2=strlen(s2+1);
15         memset(LCS,0,sizeof(LCS));
16         for(int i=1; i<=l1; ++i){
17             for(int j=1; j<=l2; ++j){
18                 if(s1[i]==s2[j]) LCS[i][j]=LCS[i-1][j-1]+1;
19                 else LCS[i][j]=max(LCS[i-1][j],LCS[i][j-1]);
20             }
21         }
22         int len=l1+l2-LCS[l1][l2];
23 
24         memset(d,0,sizeof(d));
25         d[1][1][0]=d[1][0][1]=1;
26         if(s1[1]==s2[1]) d[1][1][1]=1;
27         for(int k=2; k<=len; ++k){
28             for(int i=0; i<=l1; ++i){
29                 for(int j=0; j<=l2; ++j){
30                     if(i==0 && j==0) continue;
31                     if(i==0) d[k][i][j]=d[k-1][i][j-1];
32                     else if(j==0) d[k][i][j]=d[k-1][i-1][j];
33                     else if(s1[i]==s2[j]) d[k][i][j]=d[k-1][i-1][j-1];
34                     else d[k][i][j]=d[k-1][i-1][j]+d[k-1][i][j-1];
35                 }
36             }
37         }
38 
39         printf("Case %d: %d %lld\n",cse,len,d[len][l1][l2]);
40     }
41     return 0;
42 }

 

posted @ 2016-01-09 10:37  WABoss  阅读(183)  评论(0编辑  收藏  举报