Light OJ 1051 - Good or Bad
题目大意: 给你一个字符串,字符串由大写字母和‘?’组成,大写字母可以变成任意一个字母。现在我们定义字符串, 如果有超过三个连续的元音字母或者连续五个辅音字母,那么我们称这个字符串是“BAD”,否则称这个字符串是“GOOD”, 如果字符串既可以是“GOOD”又可以是 “BAD” 那么我们称这个字符串是“MIXED”.
题目分析:
刚开始做的时候确实没做出来,后来看了题解,确实是有点脑洞的,之前一直想不出怎么去DP。
dp[字符串的第i个位置][以第i个位置为终点连续最长的元音为i是否存在][连续最长为j是否存在] = 这个状态是否存在。
在这个DP过程中,一旦第i个位置出现了长度为3的元音或者长度为5的辅音的时候,我们后面的DP式子就不会再出现存在的情况了。
#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #include<cmath> #include<queue> #include<vector> #include<map> using namespace std; typedef long long LL; const int INF = 1e9+7; const int MAXN = 555; bool dp[MAXN][10][10];///dp[位置][元音][辅音] char str[MAXN]; bool OK(char ch) { return ch == 'A' || ch == 'E' || ch == 'O' || ch == 'I' || ch == 'U'; } void solve(int n) { memset(dp, false, sizeof(dp)); dp[0][0][0] = true; for(int i=1; i<=n; i++) { for(int j=0; j<=4; j++) { if(str[i] == '?' || !OK(str[i]))///辅音 dp[i][0][j+1] |= dp[i-1][0][j]; if(str[i] == '?' || OK(str[i])) dp[i][1][0] |= dp[i-1][0][j]; } for(int j=0; j<=2; j++) { if(str[i] == '?' || OK(str[i])) dp[i][j+1][0] |= dp[i-1][j][0]; if(str[i] == '?' || !OK(str[i])) dp[i][0][1] |= dp[i-1][j][0]; } } int good = 0, bad = 0; for(int i=0; i<=4; i++) if(dp[n][0][i]) good = 1; for(int i=0; i<=2; i++) if(dp[n][i][0]) good = 1; for(int i=1; i<=n; i++) if(dp[i][0][5] || dp[i][3][0]) bad = 1; if(good && bad) puts("MIXED"); else if(good) puts("GOOD"); else puts("BAD"); } int main() { int T, cas = 1; scanf("%d", &T); while(T --) { scanf("%s", str + 1); printf("Case %d: ", cas ++); solve(strlen(str+1)); } return 0; }