难度在省选左右.
主要思路是dp,在看了题解后才明白,主要谈谈理解.
看上去与dp毫无关系,但这个题不是利用dp求最优值,而是利用dp的子结构的递推关系.
对于长为len的字符串,可以分成很多个1个单独字符与两个字符的组合(这两个字符可变成
一字符),大串能否转换,看其构成的小串能转换.所以以长度为1开始递推到len.
f[i][j][k]:从串的i到j能否装换为字符k; ps:f[i][i][s[i]]=1(自己能转换自己.)
#include<iostream> #include<cstring> #include<cstdio> using namespace std; #define R register const int maxn=310; char s[maxn]; int tot[maxn],f[maxn][maxn][5],q[maxn][5],cnt,len; int check(char c) { if(c=='W') return 1; if(c=='I') return 2; if(c=='N') return 3; if(c=='G') return 4; } int main() { for(R int i=1;i<=4;++i) scanf("%d",&tot[i]); for(R int i=1;i<=4;++i) { for(R int j=1;j<=tot[i];++j) { char k[10]; scanf("%s",k);//不加& q[++cnt][0]=i; q[cnt][1]=check(k[0]); q[cnt][2]=check(k[1]); } } scanf("%s",s+1); len=strlen(s+1);//注意strlen(s+1)!=strlen(s)+1; for(R int i=1;i<=len;++i) f[i][i][check(s[i])]=1; for(R int i=len;i>=1;--i) for(R int j=i+1;j<=len;++j) for(R int k=i;k<j;++k)//k+1<j =>k<j; for(R int t=1;t<=cnt;++t) if(f[i][k][q[t][1]]&&f[k+1][j][q[t][2]]) f[i][j][q[t][0]]=1; int flag=0; if(f[1][len][1]) flag=1,cout<<"W"; if(f[1][len][2]) flag=2,cout<<"I"; if(f[1][len][3]) flag=3,cout<<"N"; if(f[1][len][4]) flag=4,cout<<"G"; if(!flag) cout<<"The name is wrong!"; return 0; }