AOJ 2709 - 真っ暗な部屋
解法
真っ暗な部屋が多くて16個しかないので、真っ暗な部屋に関する何かしらの情報をbitで持つことができます。
基本的な考え方は、幅優先探索です。
例えば回指示を出すとしたとき、指示列の選び方は種類になります。全ての部屋に対して、個の指示を適用していき、明るい部屋に到達するかどうかを調べることで、を小さい方から試していけばいつか答えが求まります。を固定したときに調べるためには、1つの指示列を処理するのにだけかかるので、になります。もちろんこれでは間に合いません。そこで次のような考え方をします。
まず、真っ暗な部屋全てにA君を立たせます。つまり、A君はこの時点で人いて、全て違う部屋に立っています。その後、種類ある指示のうち、1つを選んで全てのA君に対して同じ指示を出します。
すると、人いるA君のうち人(0以上以下)は明るい部屋に到達することができます。
残った人について、また種類の中から好きな指示を出し、暗い部屋にいるA君が0人になるまで繰り返せば、幅優先探索によって答えを求めることができます。ここで、現在暗い部屋に残っているA君の状態は、それぞれの暗い部屋にA君が"いる"or"いない"の2通りなので、全体でとなります。ある部屋にA君が複数人いたとしても、全員に同じ指示を出しているので、1人だけいれば十分です。これは、最初に言ったようにが16以下のため、bitで状態を考えることができます。
ですが、この考え方でも、指示の種類が膨大なためまだ間に合いません。
そこで、暗い部屋にA君がいるかどうか、という状態が通りしかないことに注目すると、
dp[S] = 暗い部屋にA君がいるかどうかの状態がSになるような指示列の長さの最小値
とすると、これはで解くことができます。現在の状態Sに対しての指示が通りで、1つの指示をSに対して適用するのにかかります。
状態Sについて、左から桁目をにA君がいるとき1、いないとき0とすると、
初期状態が
dp[ ] = 0
そして答えは
dp[0]
となります。
幅優先探索をすると、すでにある状態Sにたどり着いたかどうか(dp[S]が埋まっているかどうか)さえわかれば、遷移を気にせずに答えが求まります。