bit全探索 arc031 b 深さ優先探索 atcoder

ARC031 B - 埋め立て

ARC031 B - 埋め立て
Feb. 2, 2020, 1:52 p.m.

目次

問題

https://atcoder.jp/contests/arc031/tasks/arc031_2

入力

$c_1 c_2 ... c_{10}$
$c_{11} c_{12} ... c_{20}$
...
$c_{91} c_{92} ... c_{100}$.

  • $c_i$ - xo.

出力

すべてのoが4近傍(上下左右)で繋がっているかどうかを判定する問題です.
ただし、任意の1マスだけxoに変えることが出来ます.

解説

$H \times W$が$100$と十分小さいのですべてのxについてoに変換してみてoがすべて繋がるかを試してみることが出来ます.
全マスなのでざっくりと計算量は$O(H W) = O(100)$です.

すべてのマスが繋がっているかの確認には、深さ優先探索を使うことが出来ます.
oに変えたマスからスタートし、xに変更し、次の4近傍のうちoのところに進みます.
そしてxに変更し、・・・と進めなくなるまで繰り返します.
この深さ優先探索た終了したら、すべてのマスをチェックしてすべてxに変更されていたらすべてのoが繋がっていたと判定出来ます.
まだoが残っていたら繋がっておらず孤立していたということです.

このようにして、 bit全探索のうち1つでもすべてのoを繋げられるパターンを見つけたらその時点で答えは"YES"です.
最後まで見つけられなければ"NO"です.

計算量

bit全探索で$O(H W)$.
その中の深さ優先探索で$O(H W)$.

$$
O((H W)^2)
$$

解答

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
#define MAX_N 10

Int H, W;
vector<bool> C(MAX_N*MAX_N, true);

void input() {
  char x;
  H = W = 10;
  loop(h,0,H) {
    loop(w,0,W) {
      cin >> x;
      if (x == 'x') C[h*W + w] = false;
    }
  }
}

void dfs(Int x, Int y, Int depth, vector<bool> &c) {
  c[y*W+x] = false;
  loop(dy,-1,2) {
    loop(dx,-1,2) {
      if (dy != 0 && dx != 0) continue;
      Int x_ = x + dx, y_ = y + dy;
      if (x_ < 0 || W <= x_ || y_ < 0 || H <= y_) continue;
      if (!c[y_*W + x_]) continue;
      dfs(x_, y_, depth+1, c);
    }
  }
}

bool bit(Int x, Int y, vector<bool> c) {
  c[y*W+x] = true;
  dfs(x, y, 0, c);
  loop(h,0,H) {
    loop(w,0,W) {
      if (c[h*W+w]) return false;
    }
  }

  return true;
}

void solve() {
  loop(h,0,H) {
    loop(w,0,W) {
      if (bit(w, h, C)) {
        cout << "YES" << endl;
        return;
      }
    }
  }

  cout << "NO" << endl;
}

int main(void) {
  input();
  solve();
  return 0;
}