目次

AtCoder Beginner Contest 197(Sponsored by Panasonic)D,E,F問題メモ

AtCoder Beginner Contest 197(Sponsored by Panasonic)

全探索、幾何、DP、など比較的バラエティに富んだ問題セットで面白かった。

D - Opposite

D - Opposite

問題

解法

回転させる解法

$N$ 角形の中心の座標は $\dfrac{p_0+p_{N/2}}{2}$ でわかる。 $p_1$ は、そこを中心として $p_0$ を $\dfrac{360}{N}$ 度だけ回転させたもの。

回転を扱うときは中心を原点に持ってきた方がやりやすいので、全体を平行移動して、回転させ、元に戻す。
平行移動後の $p_0$ を $p'_0 = (x'_0,y'_0)$、回転角 $\theta = \dfrac{360}{N}$ として、行列を以下のようにかけるとよい。

\begin{eqnarray} \begin{pmatrix} x'_1 \\ y'_1 \end{pmatrix} = \begin{pmatrix} \cos\theta & -\sin\theta \\ \sin\theta & \cos\theta \end{pmatrix} \begin{pmatrix} x'_0 \\ y'_0 \end{pmatrix} \end{eqnarray}

また、複素平面でも回転を扱える。
$(x,y)$ を $x+yi$ に対応させると、$p'_1 = p'_0 \times (\cos\theta + i\sin\theta)$ となる。

Python3

直角三角形を使った解法

$p_0,p_1,p_{N/2}$ は $p_1$ を直角とした直角三角形である。

円周角は中心角の半分なので、$\angle p_0p_{N/2}p_1 = \dfrac{360}{2N}$ となる。

三角関数から各辺の長さが求まるので、2頂点の座標とあわせて、残り1点を特定できる。

E - Traveler

E - Traveler

問題

解法

$C_i$ が小さい順に、同じ整数が書かれたボールを全回収する、を繰り返すことになる。

同じ整数 $c$ が書かれた中で左端と右端のボールの座標をそれぞれ $l_c,r_c$ とすると、 $c$ のボールを回収するフェイズでは、絶対に $l_c$ から $r_c$ までは移動する必要があり、またその間に他の $c$ のボールは回収できる。

つまり、$c$ より小さい数字のボールを回収し終えた座標を $p$ とすると、以下の2通りの移動のみを考えて、損しない。

$c$ のボールを回収し終えた瞬間にいる可能性のある座標は $l_c$ か $r_c$ の2通りということになり、これをもってDPする。

最後に原点に戻る操作を忘れないように注意。
便宜的に $c$ がめちゃ大きいボールを原点に置いておくと、DP更新と同じ処理で書ける。

Python3

F - Construct a Palindrome

F - Construct a Palindrome

問題

解法

持つ状態がちょっと特殊な最短経路探索。

回文を、両端から構成していくことを考える。
頂点を組で考えて、$1$ と $N$ から、どちらからも同じ文字が書かれた辺をたどっていく。

 ,-- a --②--...--⑤-- b --, ,--,
①-- b --③--...--⑥-- c --Ⓝ   a
 `-- c --④--...--⑦-- d --' `--'

上記のような場合は、$(1,N)$ からは $(3,5),(4,6),(2,N)$ などに行ける。回文の長さは2増える。

この頂点の組を、最短経路探索における“頂点”(ステート)とすると、 各ステートは両端からそこまでは回文となることが保証されていて、残りの間の埋め方を探索していくことになる。

また、あるステートからゴール(残りの間の文字を回文となるよう最短で埋める)までのコストは、 そのステートだけに依存する(たとえばそのステートへのたどり着き方などに依存しない)ので、 通常の最短経路探索と同じように、より悪いコストで同じステートに着いたときは、捨ててよい。

コストの増え方は全て +2 なので、Dijkstraを使わずともBFSで求められる。

ただし、終了条件に注意が必要。2通りある。

BFSで探索中、Aが見つかったらそれが最小コストで確定するが、Bが見つかってもまだ確定しない。
キューの次に、同じコストでAに当てはまるものが控えているかも知れない。

Bが見つかったら暫定の答え $ans$ として覚えておき、キューから取り出されるコストが $ans$ 以上になったら、そこで確定する。

計算量

最短経路グラフにおける頂点(ステート)の個数は、元のグラフの頂点の組なので $O(N^2)$。

最短経路グラフの辺 $((a,b),(c,d))$ は、元のグラフで2本の辺 $(a,c),(b,d)$ が存在する必要があり、これも辺の組み合わせとなるので個数は $O(M^2)$。

$10^6$ 頂点 $10^6$ 辺の最短経路探索なら、十分間に合う。

Python3