キーエンスプログラミングコンテスト2022(AtCoder Beginner Contest 274)G問題メモ

G - Security Camera 3

問題

  • $H \times W$ の、空きマス'.'と壁マス'#'からなるグリッドが与えられる
  • 監視カメラを設置する
    • 監視カメラは、空きマスに上下左右の方向を決めて設置できる
    • 各監視カメラは、設置された方向の直線上の空きマスを壁マスにぶつかるまで監視できる(設置されたマスを含む)
  • 全ての空きマスを監視するために必要な監視カメラの最小数を答えよ
  • $1 \le H,W \le 300$

解法

燃やす埋める問題。(に必ずしも帰着しなくてもいいけど、自分が知ってるフォーマットに当てはめるにはそれが近かった)

まず、監視カメラは、上か左が壁かグリッド外である空きマスに、下か右を向けて置くと考えてよい。

.#...←....#..  ここに左向きのカメラを設置するくらいなら
.#.......←#..  こう設置した方が絶対にいいし、
.#→.......#..  それはこう設置するのと全く変わらない。上下も一緒

すると各マスにつき「下方向に監視されるならこの監視カメラ」「右方向ならこのカメラ」というのが一意に決まる。
このようなカメラを、マス $c$ に対し、それぞれ $D(c),R(c)$ とする。

カメラ候補を頂点として、「使う」「使わない」の燃やす埋める問題として考える。

  • 使う場合はコスト1
  • 使わない場合はコスト0
1#2
345

 ,--0-- →1 --1--,    S側に属する: 使う
 |               |    T側に属する: 使わない
 |--0-- →2 --1--|
 |               |
S---0-- →3 --1---T
 |               |
 |--0-- ↓1 --1--|
 |               |
 |--0-- ↓2 --1--|
 |               |
 `--0-- ↓4 --1--'

で、監視されないマスがあってはいけないので、各マス $c$ につき、 「$D(c)$ と $R(c)$ がともに「使わない」であってはいけない(コスト無限大)」という制約を課したい。

一般的な燃やす埋めるでは、2つの頂点が違う側に属した時のコストは設定できるが、同じ側に属したときは設定できない。

だが今回の場合は下向きカメラと右向きカメラの間にしか辺が張られないことが明らかなので (下向き同士、右向き同士に制約は課されないので)、 どちらか(例えば下向き)だけ、「使う」「使わない」の意味合いを反転させてしまえばよい。

 ,--0-- →1 --1--,    ┐ 
 |               |    │S側に属する: 使う
 |--0-- →2 --1--|    │T側に属する: 使わない
 |               |    │
S---0-- →3 --1---T   ┘
 |               |
 |--1-- ↓1 --0--|    ┐
 |               |    │S側に属する: 使わない
 |--1-- ↓2 --0--|    │T側に属する: 使う
 |               |    │
 `--1-- ↓4 --0--'    ┘

こうした上で、例えば「→1と↓2がともに使わないであってはいけない」なら、 ↓2から→1にコスト無限大の辺を張ることで制約が表現できる。

$S→T$ に最大流を流せば答え。

Python3

programming_algorithm/contest_history/atcoder/2022/1022_abc274.txt · 最終更新: 2022/11/24 by ikatakos
CC Attribution 4.0 International
Driven by DokuWiki Recent changes RSS feed Valid CSS Valid XHTML 1.0