公式

B - Looped Rope 解説 by MMNMM


この問題を解くには、すべてのマスについて次の \(2\) つの条件のうち少なくとも \(1\) つを満たすか確認すればよいです。

  • マスが白で塗られている
  • 上下左右で隣り合っているマスのうち \(2\) つか \(4\) つが黒で塗られている

上の条件のどちらも満たさないマスが \(1\) つでもあれば答えは No 、\(1\) つも存在しなければ答えは Yes です。

この処理は、番兵を用いると比較的簡単に実装することができます。

番兵 (sentinel) とは、グリッドや配列に対して操作を行う際に実際のデータの外側などに配置される特殊なデータのことをいいます。 番兵は、操作の際に行う条件分岐をシンプルにすることを目的として用いられます。 例えば、グリッド上に通れるマスと障害物マス(通れないマス)があり、グリッドの外側に出ることができないような場合に「障害物マスへは進まない」「外側のマスへは進まない」の \(2\) つの条件分岐を書くかわりに、グリッドの外側に障害物マスを設置することで前者の条件分岐だけを用いて処理を行うことができるようになります。

今回の問題では、与えられたマス目の周囲に白で塗られたマスを配置することで、上下左右に隣接するマスが存在するかどうかの分岐を書かなくてよくなります。

実装例は以下のようになります。

#include <iostream>
#include <vector>
using namespace std;

int main() {
    int H, W;
    cin >> H >> W;
    
    vector field(H + 2, string(W + 2, '.')); // すべて白マスの、上下左右に 1 列ずつ広げたマス目を用意する

    for (int i = 1; i <= H; ++i) {
        string S;
        cin >> S;
        field[i] = '.' + S + '.'; // 入力の左右に白マスを追加しておく
    }

    for (int i = 1; i <= H; ++i) {
        for (int j = 1; j <= W; ++j) { // すべてのマスについて
            int black_count = 0; // 周囲の黒マスの個数
            if (field[i - 1][j] == '#')
                ++black_count;
            if (field[i][j - 1] == '#')
                ++black_count;
            if (field[i][j + 1] == '#')
                ++black_count;
            if (field[i + 1][j] == '#')
                ++black_count;

            if (field[i][j] == '#' && black_count != 2 && black_count != 4) {
                // 条件を満たさないマスがあったら、No を出力して終了
                cout << "No" << endl;
                return 0;
            }
        }
    }

    // すべてのマスが条件を満たすので、Yes を出力して終了
    cout << "Yes" << endl;
    return 0;
}
H, W = map(int, input().split())

# 上下左右に 1 マスずつ白マスを広げたマス目を用意する
field = ['.' * (W + 2)] + ['.' + input() + '.' for i in range(H)] + ['.' * (W + 2)]

for i in range(1, H + 1):
    for j in range(1, W + 1):
        black_count = 0 # 周囲の黒マスの個数
        if field[i - 1][j] == '#':
            black_count += 1
        if field[i][j - 1] == '#':
            black_count += 1
        if field[i + 1][j] == '#':
            black_count += 1
        if field[i][j + 1] == '#':
            black_count += 1
        
        if field[i][j] == '#' and black_count != 2 and black_count != 4:
            # 条件を満たさないマスがあったら、No を出力して終了
            print('No')
            exit(0)

# すべてのマスが条件を満たすので、Yes を出力して終了
print('Yes')

投稿日時:
最終更新: