「BZOJ1055」[HAOI2008] 玩具取名 - 区间动规 - 记忆化搜索
[HAOI2008]玩具取名
Time Limit: 10 Sec Memory Limit: 162 MB
Submit: 2486 Solved: 1448
Hint
W可以变成II所以IIII可以缩成WW IN均能变成WW所以WW又可以缩成I或者N 所以最终答案应该按照“WING”的顺序输出IN
[数据范围]
\(100\)% 数据满足Len<= \(200\),W、I、N、G<= \(16\)
分析
DP,写的记忆化搜索。f[i][j][k]表示区间[i,j]能否转化成k
代码
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
char s[210];
int num[5],list[210][3],tot,f[210][210][5],len;
bool p;
inline int check(char i){
if(i=='W') return 1;
if(i=='I') return 2;
if(i=='N') return 3;
if(i=='G') return 4;
}
int main(){
for(register int i=1;i<=4;++i) scanf("%d\n",&num[i]);
for(register int i=1;i<=4;++i){
for(register int j=1;j<=num[i];++j){
char ss[5];
scanf("%s",ss);
list[++tot][0]=i;
list[tot][1]=check(ss[0]);
list[tot][2]=check(ss[1]);
}
getchar();
}
gets(s+1); len=strlen(s+1);
for(register int i=1;i<=len;++i) f[i][i][check(s[i])]=1;
for(register int i=len;i>0;--i)
for(register int j=i+1;j<=len;++j)
for(register int k=i;k<j;++k)
for(register int l=1;l<=tot;++l)
if(f[i][k][list[l][1]]&&f[k+1][j][list[l][2]])
f[i][j][list[l][0]]=1;
for(register int i=1;i<=4;++i)
if(f[1][len][i]){
p=1;
if(i==1) printf("W");
if(i==2) printf("I");
if(i==3) printf("N");
if(i==4) printf("G");
}
if(!p) printf("The name is wrong!\n");
return 0;
}