mayoko’s diary

プロコンとかいろいろ。

SRM 544 div1 med: FlipGame

問題

TopCoder Statistics - Problem Statement

H*W の盤面があり, それぞれのセルには 0 か 1 が書かれている。これを以下の操作を繰り返すことでセルに書かれた数をすべて 0 にしたい。

操作:盤面の辺を通る経路で, 左上から右下まで最短経路で行く。最短経路の左側のセルをすべてフリップ(0 -> 1, 1 -> 0)する

最小で何回の操作で目的を達成できるか。

解法

貪欲法でいけます。

各ステップに, 上から順番にどこまでフリップするかを考えます。
フリップする行はなるべく少ないほうが良いので, 最も右端にある 1 のところまでフリップさせる, ということを繰り返せば良いです。

class FlipGame {
public:
    int minOperations(vector <string> board) {
        int H = board.size(), W = board[0].size();
        int ans = 0;
        while (1) {
            bool finish = true;
            for (int i = 0; i < H; i++) for (int j = 0; j < W; j++) {
                if (board[i][j] == '1') finish = false;
            }
            if (finish) break;
            int nc = 0;
            for (int i = 0; i < H; i++) {
                // nc 以降に 1 がないか探す
                int cut = W;
                for (; cut > nc; cut--) {
                    if (board[i][cut-1] == '1') break;
                }
                // nc までフリップさせる
                nc = cut;
                for (int j = 0; j < nc; j++) board[i][j] = (board[i][j]=='0' ? '1' : '0');
            }
            ans++;
        }
        return ans;
    }
};