けんちょんの競プロ精進記録

競プロの精進記録や小ネタを書いていきます

AtCoder AGC 038 A - 01 Matrix (緑色, 300 点)

これは天才パズル!!!

問題概要

 H \times W のグリッドに 0, 1 の数値を書き込む方法であって、

  • どの行をみても、それに含まれる 0 の個数と 1 の個数のうちの小さい方の個数が  A
  • どの列をみても、それに含まれる 0 の個数と 1 の個数のうちの小さい方の個数が  B

を満たすものを構築せよ。不可能な場合はその旨を報告せよ。

制約

  •  1 \le H, W \le 1000

考えたこと

とりあえず、「どの行をみても、0 と 1 の少ない方が  A 個」という状況は、下図のようにすれば実現できる。

つまり、どの行に対しても、以下のいずれかになるようにすれば、行に関する条件をクリアできる。

  •  A 個が 0 で、右  W-A 個が 1
  •  A 個が 1 で、右  W-A 個が 0

f:id:drken1215:20201111171244p:plain

この段階ではまだ列に関する条件を考慮していないことに注意。しかし列に関しても、行と同様に、上から  B 個のところでラインを引けばよさそう。そうすると、次のような解が得られる。

いい感じにすべての条件を満たす解になっている!

f:id:drken1215:20201111172950p:plain

#include <bits/stdc++.h>
using namespace std;

int main() {
    int H, W, A, B;
    cin >> H >> W >> A >> B;
    for (int i = 0; i < H; ++i) {
        for (int j = 0; j < W; ++j) {
            if (i < B && j < A) cout << 0;
            else if (i >= B && j >= A) cout << 0;
            else cout << 1;
        }
        cout << endl;
    }
}