一开始WA,以为DP写跪了,最后发现是hash数组开小了...
设dp[x][y]表示[x, y]这个区间可以化简成的最简状态,其中状态用0到15的二进制表示。
转移时候分割区间,得到两个区间的状态,然后看有没有对应的字符即可。
边界状态是区间长度为1,和区间长度为2两种。
/* Footprints In The Blood Soaked Snow */
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn = 205;
int n, W, I, N, G, hash[750], dp[maxn][maxn];
char str[maxn];
inline int gethash(char a, char b) {
return (a - 'A') * 26 + (b - 'A');
}
inline char zip(int a) {
if(a == 0) return 'W';
if(a == 1) return 'I';
if(a == 2) return 'N';
if(a == 3) return 'G';
}
inline int getans(int s1, int s2) {
int ans = 0;
for(int i = 0; i < 4; i++) for(int j = 0; j < 4; j++) {
int a = s1 & (1 << i), b = s2 & (1 << j);
if(!a || !b) continue;
ans |= hash[gethash(zip(i), zip(j))];
}
return ans;
}
inline int dfs(int x, int y) {
if(x == y) {
if(str[x] == 'W') return dp[x][y] = 1;
if(str[x] == 'I') return dp[x][y] = 2;
if(str[x] == 'N') return dp[x][y] = 4;
if(str[x] == 'G') return dp[x][y] = 8;
}
if(y - x + 1 == 2) return dp[x][y] = hash[gethash(str[x], str[y])];
if(dp[x][y]) return dp[x][y];
int ans = 0;
for(int i = x; i < y; i++) {
int l = dfs(x, i), r = dfs(i + 1, y);
if(!l || !r) continue;
ans |= getans(l, r);
}
return dp[x][y] = ans;
}
int main() {
scanf("%d%d%d%d", &W, &I, &N, &G);
for(int i = 1; i <= W; i++) {
scanf("%s", str);
hash[gethash(str[0], str[1])] |= 1;
}
for(int i = 1; i <= I; i++) {
scanf("%s", str);
hash[gethash(str[0], str[1])] |= 2;
}
for(int i = 1; i <= N; i++) {
scanf("%s", str);
hash[gethash(str[0], str[1])] |= 4;
}
for(int i = 1; i <= G; i++) {
scanf("%s", str);
hash[gethash(str[0], str[1])] |= 8;
}
scanf("%s", str); n = strlen(str);
int ans = dfs(0, n - 1);
if(!ans) {
printf("The name is wrong!\n");
return 0;
}
if(ans & 1) printf("W");
if(ans & 2) printf("I");
if(ans & 4) printf("N");
if(ans & 8) printf("G");
printf("\n");
return 0;
}