您的位置:首页 > 其它

LightOJ1013 Love Calculator(DP)

2016-01-09 10:37 423 查看
容易猜测到包含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了,有点不明觉厉。。

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int LCS[33][33];
long long d[66][33][33];
int main(){
int t;
char s1[33],s2[33];
scanf("%d",&t);
for(int cse=1; cse<=t; ++cse){
scanf("%s%s",s1+1,s2+1);

int l1=strlen(s1+1),l2=strlen(s2+1);
memset(LCS,0,sizeof(LCS));
for(int i=1; i<=l1; ++i){
for(int j=1; j<=l2; ++j){
if(s1[i]==s2[j]) LCS[i][j]=LCS[i-1][j-1]+1;
else LCS[i][j]=max(LCS[i-1][j],LCS[i][j-1]);
}
}
int len=l1+l2-LCS[l1][l2];

memset(d,0,sizeof(d));
d[1][1][0]=d[1][0][1]=1;
if(s1[1]==s2[1]) d[1][1][1]=1;
for(int k=2; k<=len; ++k){
for(int i=0; i<=l1; ++i){
for(int j=0; j<=l2; ++j){
if(i==0 && j==0) continue;
if(i==0) d[k][i][j]=d[k-1][i][j-1];
else if(j==0) d[k][i][j]=d[k-1][i-1][j];
else if(s1[i]==s2[j]) d[k][i][j]=d[k-1][i-1][j-1];
else d[k][i][j]=d[k-1][i-1][j]+d[k-1][i][j-1];
}
}
}

printf("Case %d: %d %lld\n",cse,len,d[len][l1][l2]);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: