[AOJ] No. 0621 ロシアの旗 (Russian Flag)
問題
方針
累積和
'W’, 'B’, 'R’ についてそれぞれ列ごとに累積和を取っていきます。ある列を塗り替えるコストは、\( M \) からその色の個数を引いた値なので、累積和を使って効率よく計算します。\( b_{i, j} \) を 色 \( j \) の \( i \) 行目までの累積和とします。また、\( j = 0\) を 'W’、\( j = 1\) を 'B’、\( j = 2\) を 'R’ とします。
全探索
旗の白い部分の最後の列を \( i \ (1 \leq i \leq N – 2) \) 、青い部分の最後の列を \( j \ ( i < j \leq N – 1) \) とします。このときの色を変えるコストは、
\[Mi – b_{i, 0} + M(j – i) – (b_{j, 1} – b_{i, 1}) + M(N – j) – (b_{N, 2} – b_{j, 2})\]
となります。
コード
#include <bits/stdc++.h> using namespace std; typedef long long ll; int main() { cin.tie(0); ios::sync_with_stdio(false); int N, M; cin >> N >> M; char c[N][M]; for (int i = 0; i < N; i++) { string s; cin >> s; for (int j = 0; j < M; j++) { c[i][j] = s[j]; } } int a[N][3]{}; for (int i = 0; i < N; i++) { for (int j = 0; j < M; j++) { if (c[i][j] == 'W') a[i][0]++; else if (c[i][j] == 'B') a[i][1]++; else a[i][2]++; } } int b[N + 1][3]{}; for (int i = 0; i < N; i++) { for (int j = 0; j < 3; j++) { b[i + 1][j] += b[i][j] + a[i][j]; } } int ans = 10000000; for (int i = 1; i < N - 1; i++) { for (int j = i + 1; j < N; j++) { int v = M * i - b[i][0] + M * (j - i)- (b[j][1] - b[i][1]) + M * (N - j) - (b[N][2] - b[j][2]); ans = min(ans, v); } } cout << ans << "\n"; return 0; }
ディスカッション
コメント一覧
まだ、コメントがありません