Description
某人有一套玩具,并想法给玩具命名。首先他选择WING四个字母中的任意一个字母作为玩具的基本名字。然后
他会根据自己的喜好,将名字中任意一个字母用“WING”中任意两个字母代替,使得自己的名字能够扩充得很长。
现在,他想请你猜猜某一个很长的名字,最初可能是由哪几个字母变形过来的。
100%数据满足Len<=200,W、I、N、G<=16
Solution
一开始还以为是什么奇怪的图论题,我果然菜啊
设f[i,j,k]表示i到j能否用k表示,然后暴力转移即可
Code
#include <stdio.h>
#include <string.h>
#include <algorithm>
#define rep(i,st,ed) for (int i=st;i<=ed;++i)
#define fi first
#define se second
typedef std:: pair <int,int> pair;
const int N=205;
bool f[N][N][4];
char str[N];
pair a[N][N];
int cnt[N];
int get(char x) {
if (x=='W') return 0;
if (x=='I') return 1;
if (x=='N') return 2;
if (x=='G') return 3;
}
int main(void) {
rep(i,0,3) scanf("%d",&cnt[i]);
rep(i,0,3) {
rep(j,1,cnt[i]) {
char ch[2]; scanf("%s",ch);
a[i][j]=pair(get(ch[0]),get(ch[1]));
}
}
scanf("%s",str+1); int n=strlen(str+1);
rep(i,1,n) f[i][i][get(str[i])]=1;
rep(len,1,n) {
rep(i,1,n-len) {
int j=i+len;
rep(k,0,3) rep(l,i,j) {
if (f[i][j][k]) break;
rep(t,1,cnt[k]) {
if (f[i][j][k]) break;
f[i][j][k]|=f[i][l][a[k][t].fi]&f[l+1][j][a[k][t].se];
}
}
}
}
if (f[1][n][0]) putchar('W');
if (f[1][n][1]) putchar('I');
if (f[1][n][2]) putchar('N');
if (f[1][n][3]) putchar('G');
if (!f[1][n][0]&&!f[1][n][1]&&!f[1][n][2]&&!f[1][n][3]) {
puts("The name is wrong!");
}
return 0;
}