CF round 789 B2 - Tokitsukaze and Good 01-String (hard version)
阿新 • • 發佈:2022-05-12
Tokitsukaze and Good 01-String (hard version)
貪心
兩個一組分成 \(\frac n2\) 個 01 段
- 當前這一組不相同,則運算元++,並且讓這一組變成和上一組一樣的,段數不變
- 當前這一組相同,如果和上一組相同,段數不變;如果不相同,則段數++。更新 last
#include <iostream> #include <cstring> #include <algorithm> #include <vector> #include <cmath> using namespace std; typedef long long ll; const int N = 2e5 + 10; int n; string s; int main() { ios::sync_with_stdio(false), cin.tie(0), cout.tie(0); int T; cin >> T; while(T--) { cin >> n >> s; int x = 0, y = 0; char last = ' '; for (int i = 0; i < s.size(); i += 2) { if (s[i] != s[i+1]) x++; else { if (last != s[i]) y++; last = s[i]; } } cout << x << " " << max(1, y) << endl; } return 0; }
運算元貪心 + 段數DP
記 \(f[i][0/1]\) 為前 i 段,最後一段是 00/11 的最小段數
貪心:若某一段需要操作兩次,那這個狀態就是非法的,設為 INF
其他情況dp
#include <iostream> #include <cstring> #include <algorithm> #include <vector> #include <cmath> using namespace std; typedef long long ll; const int N = 2e5 + 10; const int INF = 1e9; int n; string s; int f[N][2]; int main() { ios::sync_with_stdio(false), cin.tie(0), cout.tie(0); int T; cin >> T; while(T--) { cin >> n >> s; s = " " + s; int x = 0; //初始化 if (s[1] != s[2]) { x++; f[2][0] = f[2][1] = 1; } else { if (s[1] == '1') { //貪心運算元,這一步不能操作兩次,所以讓這種狀態不合法 f[2][0] = INF; f[2][1] = 1; } else { f[2][0] = 1; f[2][1] = INF; } } for (int i = 4; i <= n; i += 2) { f[i][0] = f[i][1] = INF; if (s[i] != s[i-1]) { x++; f[i][0] = min(f[i-2][0], f[i-2][1] + 1); f[i][1] = min(f[i-2][0] + 1, f[i-2][1]); } else { //貪心運算元,當前這一段是00,就不可能讓這一段變成11,所以f[i][1]非法 if (s[i] == '0') f[i][0] = min(f[i-2][0], f[i-2][1] + 1); else f[i][1] = min(f[i-2][0] + 1, f[i-2][1]); } } cout << x << " " << min(f[n][0], f[n][1]) << endl; } return 0; }
DP
\(f[i][0/1]\) 為前 i 段,最後一段是 00/11 的 {運算元,段數},首先滿足運算元最小,再滿足段數最小,所以可用 pair 儲存
不考慮上一個方法中:貪心:若某一段需要操作兩次,那這個狀態就是非法的,設為 INF
若需要操作兩次,就讓他操作兩次,最後取 min 時得到的也是運算元最小情況下段數最小的答案
#include <iostream> #include <cstring> #include <algorithm> #include <vector> #include <cmath> #define x first #define y second using namespace std; typedef long long ll; typedef pair<int, int> PII; const int N = 2e5 + 10; const int INF = 1e9; int n; string s; PII f[N][2]; int main() { ios::sync_with_stdio(false), cin.tie(0), cout.tie(0); int T; cin >> T; while(T--) { cin >> n >> s; s = " " + s; int x = 0; if (s[1] != s[2]) f[2][0] = f[2][1] = {1, 1}; else { if (s[1] == '1') { f[2][0] = {2, 1}; f[2][1] = {0, 1}; } else { f[2][0] = {0, 1}; f[2][1] = {2, 1}; } } for (int i = 4; i <= n; i++) { if (s[i] != s[i-1]) { f[i][0] = min(PII(f[i-2][0].x + 1, f[i-2][0].y), PII(f[i-2][1].x + 1, f[i-2][1].y + 1)); f[i][1] = min(PII(f[i-2][0].x + 1, f[i-2][0].y + 1), PII(f[i-2][1].x + 1, f[i-2][1].y)); } else { if (s[i] == '0') { f[i][0] = min(PII(f[i-2][0].x, f[i-2][0].y), PII(f[i-2][1].x, f[i-2][1].y + 1)); f[i][1] = min(PII(f[i-2][0].x + 2, f[i-2][0].y + 1), PII(f[i-2][1].x + 2, f[i-2][1].y)); } else { f[i][0] = min(PII(f[i-2][0].x + 2, f[i-2][0].y), PII(f[i-2][1].x + 2, f[i-2][1].y + 1)); f[i][1] = min(PII(f[i-2][0].x, f[i-2][0].y + 1), PII(f[i-2][1].x, f[i-2][1].y)); } } } PII ans = min(f[n][0], f[n][1]); cout << ans.x << " " << ans.y << endl; } return 0; }