您的位置:首页 > 其它

UVa1625 Color Length

2017-08-10 11:24 417 查看
题目描述

传送门

参照刘汝佳书上的思路。一开始自己写了个记忆化搜索超时了,哪位高人能指点一下超时的原因…

//TLE!
#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
int l1,l2,b1[200],b2[200],e1[200],e2[200],d[5010][5010],cnt=0;
//d[i][j]表示s1,s2分别取了i,j个颜色,还需要的L值
char s1[20010],s2[20010];
int dp(int i,int j,int tot){//tot表示已经出现但未结束的颜色的总数
if(i>l1||j>l2) return 100000000;
if(d[i][j]>-1) return d[i][j];
d[i][j]=tot;
int t1=tot,t2=tot;
if(i+1==b1[s1[i+1]]&&(b2[s1[i+1]]>j||b2[s1[i+1]]==-1)) t1++;
if(i+1==e1[s1[i+1]]&&(e2[s1[i+1]]<=j||b2[s1[i+1]]==-1)) t1--;
if(j+1==b2[s2[j+1]]&&(b1[s2[j+1]]>i||b1[s2[j+1]]==-1)) t2++;
if(j+1==e2[s2[j+1]]&&(e1[s2[j+1]]<=i||b1[s2[j+1]]==-1)) t2--;//计算其他的tot
return d[i][j]+=min(dp(i+1,j,t1),dp(i,j+1,t2));//转移
}
int main(){
int t;
cin>>t;
while(t--){
memset(b1,-1,sizeof(b1));
memset(b2,-1,sizeof(b2));
scanf("%s%s",s1+1,s2+1);
l1=strlen(s1+1),l2=strlen(s2+1);
for(int i=1;i<=l1;i++){//计算s1里每种颜色的开始和结束位置(b1表示开始的位置,e1表示结束的位置,下同)
if(b1[s1[i]]==-1) b1[s1[i]]=i;
e1[s1[i]]=i;
}
for(int i=1;i<=l2;i++){//计算s2里每种颜色的开始和结束位置
if(b2[s2[i]]==-1) b2[s2[i]]=i;
e2[s2[i]]=i;
}
memset(d,-1,sizeof(d));
d[l1][l2]=0;
printf("%d\n",dp(0,0,0));
}
return 0;
}


后来换成递推的就AC了

#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
int l1,l2,b1[200],b2[200],e1[200],e2[200],d[5010][5010],tot[5010][5010];
char s1[20010],s2[20010];
int main(){
int t;
cin>>t;
while(t--){
memset(b1,-1,sizeof(b1));
memset(b2,-1,sizeof(b2));
scanf("%s%s",s1+1,s2+1);
l1=strlen(s1+1),l2=strlen(s2+1);
for(int i=1;i<=l1;i++){
if(b1[s1[i]]==-1) b1[s1[i]]=i;
e1[s1[i]]=i;
}
for(int i=1;i<=l2;i++){
if(b2[s2[i]]==-1) b2[s2[i]]=i;
e2[s2[i]]=i;
}
for(int i=0;i<=l2+1;i++) d[l1+1][i]=1000000000;
for(int i=0;i<=l1+1;i++) d[i][l2+1]=1000000000;
d[l1][l2]=0;
tot[0][0]=0;
for(int i=0;i<=l1;i++){
for(int j=0;j<=l2;j++){
int t1=tot[i][j],t2=tot[i][j];
if(i+1==b1[s1[i+1]]&&(b2[s1[i+1]]>j||b2[s1[i+1]]==-1)) t1++;
if(i+1==e1[s1[i+1]]&&(e2[s1[i+1]]<=j||b2[s1[i+1]]==-1)) t1--;
if(j+1==b2[s2[j+1]]&&(b1[s2[j+1]]>i||b1[s2[j+1]]==-1)) t2++;
if(j+1==e2[s2[j+1]]&&(e1[s2[j+1]]<=i||b1[s2[j+1]]==-1)) t2--;
tot[i+1][j]=t1;tot[i][j+1]=t2;
}
}
for(int i=l1;i>=0;i--){
for(int j=l2;j>=0;j--){
if(i==l1&&j==l2) continue;
d[i][j]=min(d[i+1][j],d[i][j+1])+tot[i][j];
}
}
printf("%d\n",d[0][0]);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: