配点: 300 点 / 実行時間制限: 2 sec / メモリ制限: 1024 MB / Difficulty: 247
問題概要
のマス目が与えられる。以下、上から
行目、左から
列目のマスをマス
で表す。
マス目の状態は 個の長さ
の文字列
によって以下のように表される。
#: マスは黒く塗られている。
.: マスは白く塗られている。
?: マスはまだ塗られていない。
ここで、まだ塗られていないマスをそれぞれ白または黒で塗ることで、黒マス全体が長方形をなすようにしたい。より具体的には、ある4つの整数の組 が存在して、次が成り立つようにしたい。
- マス
は、
かつ
を満たすとき、黒く塗られている。そうでないとき、白く塗られている。
そのようなことが可能か判定せよ。
制約
は整数で、
を満たす。
- 黒く塗られたマスが1つ以上存在する。
考察
黒いマスがどの領域にあるかを調べ(領域 とする)、
内を黒く塗って長方形を作ることを考える。
まず、 内の左上、左下、右上、右下のマスを求める必要があるわけだが、これは
個の黒いマスが
であるとき、
と定義すれば、それぞれのマスは
- 左上 :
- 左下 :
- 右上 :
- 右下 :
と書ける。
この4マスで囲まれる領域 の中に、白いマスが1個でもあったら
内で黒い長方形を作ることはできない。逆にそうでない場合は、
?のマスを黒く塗ることで黒い長方形を作ることができる。
実装例
#include <bits/stdc++.h> using namespace std; #define rep(i, start, end) for (auto i = (start); (i) < (end); (i)++) template <typename T> inline bool chmax(T &a, T b) { return ((a < b) ? (a = b, true) : (false)); } template <typename T> inline bool chmin(T &a, T b) { return ((a > b) ? (a = b, true) : (false)); } // ======================================== // int main() { int H, W; cin >> H >> W; vector<string> S(H); rep(i, 0, H) cin >> S[i]; int min_i = H, max_i = -1, min_j = W, max_j = -1; rep(i, 0, H) rep(j, 0, W) { if (S[i][j] == '#') { chmin(min_i, i); chmax(max_i, i); chmin(min_j, j); chmax(max_j, j); } } rep(i, 0, H) rep(j, 0, W) { if ((min_i <= i && i <= max_i) && (min_j <= j && j <= max_j)) { if (S[i][j] == '.') { cout << "No" << endl; return 0; } } } cout << "Yes" << endl; return 0; }
実装時間: 10分
コメント
「具体的には...」の後の文は数式がごちゃっと並んでいて難しそうに見えるので読み飛ばしがちだが、きちんと読むと愚直な実装方法が見えてくるので、詰まったときは丁寧に読みたい。