记忆化搜索(正解是区间dp)
我们定义dfs(l,r,k)表示区间l~r能不能用第k种字符展开,然后爆搜就好了,用了一个字符-->数字的映射
代码
//By AcerMo
#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
int li[5],c[300],f[300][300][5];
char n[5]={'W','I','N','G'},name[300],sw[5][300][2];
inline bool dfs(int l,int r,int k)
{
if (l==r) return name[l]==n[k];
if (f[l][r][k]!=-1) return f[l][r][k];
int ans=0;
for (int i=1;i<=li[k];i++)
for (int j=l;j<r;j++)
if (dfs(l,j,c[sw[k][i][0]])&&dfs(j+1,r,c[sw[k][i][1]]))
{ans=1;break;}
return f[l][r][k]=ans;
}
signed main()
{
scanf("%d%d%d%d",&li[0],&li[1],&li[2],&li[3]);
for (int i=1;i<=li[0];i++) scanf("%s",sw[0][i]);
for (int i=1;i<=li[1];i++) scanf("%s",sw[1][i]);
for (int i=1;i<=li[2];i++) scanf("%s",sw[2][i]);
for (int i=1;i<=li[3];i++) scanf("%s",sw[3][i]);
c['W']=0;c['I']=1;c['N']=2;c['G']=3;bool flag=0;
scanf("%s",name+1);li[4]=strlen(name+1);
memset(f,-1,sizeof(f));
for (int i=0;i<4;i++)
if (dfs(1,li[4],i)) flag=1,cout<<n[i];
if (!flag) puts("The name is wrong!");
return 0;
}