BZOJ 1055 [HAOI2008]玩具取名
一个人首先给一个玩具取名为WING中的一个字符,且W,I,N,G分别可以变成w,i,n,g种两个WING中的字符,给出玩具最终的名字,问最初的名字可以为那些字符
定义dp[l][r][k]为[l,r]是否可以变成一种第k个字符
#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
int wing[4]; char WING[4][20][5];
char s[205];
int f[205][205][4];
int arc(char c) {
switch(c) {
case 'W': return 0;
case 'I': return 1;
case 'N': return 2;
case 'G': return 3;
}
}
int DP(int l, int r, int k) {
if(l == r) return arc(s[l]) == k;
int & res = f[l][r][k];
if(res != -1) return res;
res = false;
for(int i = l; i < r; i++) {
for(int j = 0; j < wing[k]; j++)
res |= DP(l, i, arc(WING[k][j][0]))
&& DP(i + 1, r, arc(WING[k][j][1]));
}
return res;
}
int main() {
for(int i = 0; i < 4; i++) scanf("%d", &wing[i]);
for(int i = 0; i < 4; i++)
for(int j = 0; j < wing[i]; j++)
scanf("%s", WING[i][j]);
scanf("%s", s);
int len = strlen(s);
memset(f, -1, sizeof(f));
bool ans = 1;
if(DP(0, len - 1, 0)) putchar('W'), ans = 0;
if(DP(0, len - 1, 1)) putchar('I'), ans = 0;
if(DP(0, len - 1, 2)) putchar('N'), ans = 0;
if(DP(0, len - 1, 3)) putchar('G'), ans = 0;
if(ans) printf("The name is wrong!");
putchar('\n');
return 0;
}