まず、魔法を使わないで移動できる範囲を求めます。
各マスの領域ごとではなく、マスの角ごとに管理します。マス目全体の周も考えると、 の大きさになります。それぞれを頂点と呼ぶことにします。
ある頂点から隣り合う頂点に遷移できない条件は、ある つのマスの両方に木が生えていることです。
これらに注意して BFS (幅優先探索)をすると、正しく求められます。
次に、魔法を 回使うときの BFS の動作を考えます。
回魔法を使うことは、 BFS ですでに遷移している各頂点から、
として遷移することとみなせます。
これを高速に実現するために、元の BFS とはそれぞれ別のテーブルを用いて
を行います。
これは、距離テーブルの代わりに「あと何回遷移できるか」を記録すれば可能です。
以上、全体で 段階の BFS をします。
段階の BFS を繋げて動作させるには、ある段階で到達できた頂点をそのまま次の段階の BFS のキューに追加すればよいです。 段階目から 段階目に戻るときも同じです。
この 段階の 周分は 時間でできます。
求めるものは、 段階目の距離テーブルの外周に初めて来た時に何周していたかです。
高々 周なので全体で 時間です。
段階目の距離テーブルは明らかに再利用できます。
段階目と 段階目は距離テーブルの再利用には注意が必要です。
例えば、 段階目で到達した頂点から、 段階目・ 段階目の BFS で全く移動できない場合、次の 段階目ではすでに到達した頂点から探索する必要があります。
図はそれを表す距離テーブルの例です。 0
の頂点から改めて探索しないと 周目で外周 .
に到達しないことに注意してください。
入力, 1周目, 2周目 3 3 1 1 ....... ....... ###### .xxxxx. .01110. ###### ..010x. .o1110. .##### ..010x. .o1110. ###### .x010x. .01110. ###### .xxxxx. .01110. ###### ....... .......
どの頂点を再度探索すればよいかは、 次元的に考察でき、その結果「あと 回以上移動できる」状態の頂点を再探索することは「あと 回移動できる」状態の頂点の再探索でカバーできます。
前回の探索で「あと 回移動できる」状態になった頂点のみ探索しなおせば十分です。
各段階の BFS では各頂点は高々 回しか探索しないので、全体で 時間になります。