[2020 ICPC 臺北新竹 E] A Color Game
阿新 • • 發佈:2021-09-13
https://codeforces.com/gym/102835/problem/E
題意:
有\(7\)種顏色,給定顏色序列,如果子序列的長度大於\(m\),且所有元素都相同,子序列就可以被消掉。問最終能否把序列消完。
思路:
一段連續的序列可以只消除一部分,沒有比較好的貪心策略,考慮區間\(DP\)。只有顏色相同的區間才能合併,且當前區間可能進行過一些消除操作,不是原來的區間,考慮陣列後面多加一維,\(dp[i][j][k]\)表示區間內顏色只剩下\(k\)時,\(k\)最多的數量是多少。在合併區間時,可能只消除一邊的區間,設\(ok[i][j]\)表示區間能否被完全消除。接下來大力合併即可。
#include <bits/stdc++.h> using namespace std; typedef long long ll; const int N = 5e2 + 7; char s[N], cor[] = {'R', 'G', 'B', 'C', 'M', 'Y', 'K'}; int dp[N][N][7], id[N]; bool ok[N][N]; void run() { int n, m; scanf("%s %d", s, &m); n = strlen(s); if (m == 1) { puts("Yes"); return; } for (int i = 0; i < n; ++i) { for (int j = 0; j < 7; ++j) { if (cor[j] == s[i]) { id[i] = j; break; } } } for (int i = 0; i < n; ++i) { dp[i][i][ id[i] ] = 1; } for (int len = 2; len <= n; ++len) { for (int i = 0; i < n; ++i) { int j = i + len - 1; if (j >= n) break; for (int sub = 1; sub < len; ++sub) { int k = i + sub - 1; for (int c = 0; c < 7; ++c) { if (dp[i][k][c] && dp[k + 1][j][c]) { dp[i][j][c] = max(dp[i][j][c], dp[i][k][c] + dp[k + 1][j][c]); } if (dp[i][k][c] && dp[k + 1][j][c] && dp[i][k][c] + dp[k + 1][j][c] >= m) { ok[i][j] = 1; } if (ok[i][k]) { dp[i][j][c] = max(dp[i][j][c], dp[k + 1][j][c]); } if (ok[k + 1][j]) { dp[i][j][c] = max(dp[i][j][c], dp[i][k][c]); } } } } } if (ok[0][n - 1]) { puts("Yes"); } else { puts("No"); } } int main() { int t = 1; while (t--) run(); return 0; }