Kazun の競プロ記録

競技プログラミングに関する様々な話題を執筆します.

AtCoder Beginner Contest 278 F問題 Shiritori

問題

atcoder.jp

提出解答

atcoder.jp

問題の概要

 N 個の文字列  S_1, \dots, S_N が与えられる.

先手と後手の2人がこの  N 個の文字列を用いてしりとりをする. 先手から交互に以下を満たすような整数  i~(1 \leq i \leq N) を選ぶ.

  •  i はこれまで1回も選ばれていない.
  • 先手の第1ターン, または直前に選ばれた整数を  j としたとき,  S_j の末尾の文字と  S_i の先頭の文字が等しい.

条件を満たすような  i を選べなくなったら負けである.

両者が勝利のために最善を尽くした場合, 勝つのはどちらか?

制約

  •  1 \leq N \leq 16
  •  S_i は長さ  1 以上  10 以下の英小文字からなる文字列.

解法

bit dp で解くことにする.  \{1,2, \dots, N \} の空ではない部分集合  S と整数  i~(1 \leq i \leq N) に対して,  {\rm DP}[S,i]

  • 既に選ばれている整数の集合が  S で, 特に最後に選ばれた整数が  i である場面で回ってきた時, その人必勝ならば  T, 必敗ならば  F とする.

このとき,  S_i の先頭と末尾の文字をそれぞれ  \alpha_i, \beta_i とすると, 更新式はまだ選ばれていないしりとり可能な文字列を候補にし, 1つでもその先で必敗しなくてはならないので,

 \displaystyle {\rm DP}[S,i]=\lnot \bigwedge_{\substack{j \not \in S \\ A_i=B_j}} {\rm DP}[S \cup \{j\},j]

である.

先手必勝であるための必要十分条件は最初に選ぶ文字列で場合分けすることによって,

 \displaystyle \lnot \bigwedge_{j=1,2, \dots, N} {\rm DP}[\{j\}, j]=T

となる.