[KUPC2019] I – encode/decode 2019

スポンサーリンク

概要

問題文 →
公式解説 → 存在するか分からず
自分の提出 →

個人的に,クエリ回数 $8000~15000$ 回くらいの解法ばかり思いついて大変でした.ものによってはある程度実装してみないとクエリ回数が見積もれないのも大変.


AC 確率の検証はしていませんが,実際の提出・採点データセットで クエリ回数 $2300$ 以下 で解くことに成功しました.

以下,$K=25$ とします.$K$ を大きくすると encode 成功率は高くなり,$K$ を小さくするとクエリ回数が小さくなります.

解法

encode 方針

60 bit の情報を encode します.$4$ 方向にグリッドパスを作ります.パスの長さも定数 $K$ に固定しておきます(decode を簡単にするため).私の提出では,$K=25$ としています.

始点は,上下左右に $2$ 個ずつ動ける場所を選ぶことで,各方向が干渉しないようにしておきます.パスの形は $X$ によって決めます(後述).

decode 方針

$4$ 方向のパスの形を復元します.$4$ 回解くとして,$k=2,3,4,\ldots,K-1$ に対して次ができればよいです:パスの $k$ 番目まで分かってるとき,$k+1$ 番目を求める.

これは,パスの進行方向が右または上であるとして,

  • パスの先端から右に進もうとする.
  • 右に進めなかったと仮定した場合を想定してスタート地点に戻ろうとする.
    • スタートに着いたと言われたら,現在地はスタートであり,パスの先端の右が壁だったことになる.
    • そうでなかったらパスの先端の右は道(上は壁)だったことになる.現在地も分かる.

最悪ケースのクエリ回数は,$k$ のインクリメントごとに $2k+1$ クエリ程度使う場合で,方向ごとにクエリ回数 $K^2$ 程度(全体で $4K^2$ 程度)です.上が壁だったパターンの方がスタートまで戻らないでよいので,クエリ回数は少なくなります.

盤面が復元できたらここから $X$ を復元して(後述)終了です.

まとめ

あとは $X$ に応じた encode および $X$ の decode の詳細を説明します.

encode, decode は $4$ 方向ごとに独立に行われるので,方向を固定して,15 bit の情報を送る方法を考えます.

encode の際に,$X$ からパスの形を一意に固定してしまうと目標の形がとれるマスが全然存在しなくなるので,同じ $X$ に対してたくさんのパスがマッチするようにするのがポイントです.

グリッドの各マス目に,ランダムな $2^{15}$ 以下の整数を割り当てます.「パスの重み」とは通るマス全体の XOR とします.

  • encode:重みが $X$ であるようなパスを選ぶ.
  • decode:パスの重みを計算する.

encode は,dp により行えます.マス $(i,j)$ までのパスで重み $k$ のものが存在するかの bool 値を dp[i][j][k] として計算すればよいです.ランダムにパスをとりまくるのでも十分かもしれません.

長さ $K$ のパスで目的のものが存在する保証はできないので,ここで AC 確率バトル発生です.$K$ が小さいとここで失敗するでしょう.$K=25$ で,失敗したら始点をとりなおすロジックを入れれば AC になりました.

基本的にはパスが $2^{15}n$ 個くらい存在するなら確率 $\exp(-n)$ 程度の確率で成功するはずで,$K$ が大きいほど成功率が高くなります.

タイトルとURLをコピーしました