【题目链接】
一开始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; }