Google Code Jam 2019 Round1C : Bacterial Tactics

問題. Bacterial Tactics

 R 行,横  C 列の長方形のマス目が与えられる.各マスは空白か危険な物質が置かれている.2人のプレイヤーが交互に空白のマスを選び V型かH型のバクテリアを置くことを繰り返す.V型バクテリアは置かれたマスの隣接する上下方向の空白マスか危険な物質があるマスに順番に複製して伝搬する.ただし,危険な物質が置かれているマスにバクテリアが伝搬すると,その手を選択したプレイヤーの負けとする.同様に,H型バクテリアは水平方向に伝搬する.また,バクテリアを置くことのできないプレイヤーも負けとする.2人のプレイヤーが最適な戦略で行動したときにどちらが勝つかを判定せよ.先手番が勝つときには,初手で勝つことのできる選択肢の数も答えよ.

制約 1 \le R, C \le 15

解法.グランディ数 + 動的計画法 + 累積和

このゲームは不偏ゲームなのでグランディ数に帰着することを考える.1つのマスにバクテリアを置くと1つまたは2つの矩形領域に分割される.そこで,任意の部分矩形領域  S に1つのグランディ数  \mathscr{g}(S) を対応させることを考える. S 内でバクテリアを置くことができるマス  (r, c) に対して, (r, c) によって分割される部分領域  S_{1}, S_{2} から新たなグランディ数  \mathscr{g}_{r c} = \mathscr{g}(S_{1}) \oplus \mathscr{g} (S_{2})再帰的に求める.ただし,二項演算  \oplus はビットごとの排他的論理和である.1マスからなる矩形領域のグランディ数は,空白なら 1 ,危険な物質があるときは 0 とする. S 内のバクテリアを置くことができるマスの集合を  f(S) とすると, \mathscr{g(S)} = \mathrm{mex}_{(r, c) \in f(S)} ( \mathscr{g}_{r c} ) となる.ただし,任意の非負整数からなる集合  X に対して  \mathrm{mex} (X) X の最小除外値( minimum excluded value; mex )を表している.

後は,領域を状態として動的計画法を行えばすべての部分矩形領域のグランディ数を求めることができる.このとき,マスにバクテリアを置けるかどうかを判定するのに,危険な物質が置かれている数に関する累積和を前もって求めることによって定数時間で判定できる.

計算時間 O(N^6 \log N) N = \max(R, C) )


上では領域  S に対してバクテリアを置くことのできるマス全体  f(S) の要素を全部調べていたが,同じ行または同じ列のマスに対するグランディ数は同じになるので,行と列に対してのみ調べればよいことが分かる.これによって, O(N^6 \log N) 時間から  O(N^5 \log N) 時間に改善できた.また,最小除外値の計算に set を使用していたが,領域  S のグランディ数はその行数と列数の和以下になるのでビンソートで求めると高速化できる.これによって, O(N^5 \log N) 時間から  O(N^5) 時間に改善できた.

計算時間 O(N^5) N = \max(R, C) )

長時間格闘した後にACしたので簡潔な実装を考える気力がない.たぶん最小除外値を求める  \log を取り除ける気がするけど後で考える.(⇐ 考えた)