ゲームDP:勝ち状態を定義する

完全情報・交互手番で、合法手がなくなった人が負けるゲーム。勝ち状態は「相手を負け状態に送れる状態」です。

言語:Python / 計算量:O(N × 手の種類数)

前提:DPは「同じ続きをまとめる」

考え方

  1. 手がない状態は負け。
  2. 1つでも負け状態への手があれば勝ち。
  3. 全ての手が勝ち状態へ行くなら負け。

具体例

石を1個か3個取る。0は負け、1は勝ち、2は負け、3は勝ち。手番の人を基準に状態を定義します。

実装

n=6;win=[False]*(n+1)
for x in range(1,n+1):
    win[x]=any(x>=k and not win[x-k] for k in [1,3])
print(win[n])

注意する条件

引き分けや閉路があるゲームは単純な小さい順DPでは解けません。独立ゲームの和にはGrundy数とxorを学びます。

確認問題

1個か3個取れる石2個の局面は先手勝ち? Yes/No

解答と理由

No

1個取るしかなく、相手が最後の1個を取れます。

実装課題

石N個から毎手1個か3個取る。取れない側が負け。最適プレイで先手勝ちなら First、負けなら Second。0≤N≤10^6。

入力:
6
出力:
Second
参考実装
n=int(input());win=[False]*(n+1)
for x in range(1,n+1):win[x]=any(x>=k and not win[x-k] for k in [1,3])
print("First" if win[n] else "Second")

読了の記録・下書き・メモへ

関連する公式資料・課題