Google Code Jam Round 2

負けた…
http://fxp.infoseek.ne.jp/img/gcj_2005_r2.png

        • -

今回の問題は300点、450点、1000点の3つ。
時間は前と同じ75分。


300点問題は、
迷路の中を複数のプレイヤーが陣形を崩さないように探索するとき、
誰か一人がゴールにたどり着くまでの最短距離を求めよ、というもの。
普通に幅優先で終わりかと思われるが、
いろいろとめんどくさい。とてもめんどくさい。
ついに300点問題でこの難易度になったか、としみじみ思う。
35分もかかってSubmit。


この時点で3問解くのをあきらめる。
400点問題は

function hash(bits)
  set key = 0
  prepend '0' to bits
  for( i = 1 to lengthof(bits)-1 )
    if(bits[i-1]=='0' and bits[i] == '0') key = (key * mults[0] + adds[0]) % size
    if(bits[i-1]=='0' and bits[i] == '1') key = (key * mults[1] + adds[1]) % size
    if(bits[i-1]=='1' and bits[i] == '0') key = (key * mults[2] + adds[2]) % size
    if(bits[i-1]=='1' and bits[i] == '1') key = (key * mults[3] + adds[3]) % size
  end
  return key
end

というアルゴリズムに基づきハッシュを生成する。
nビット以下のすべてのデータに対してハッシュを生成したとき、
もっとも多く生成されたハッシュの生成回数を求める、というもの。
ちなみに、ビット数は50まで、sizeは10000まで。
これは、nビットまでの頻度表(と直前のビット)があれば
n+1ビットに対するものが求まるので、DPできる。
これは思いついたら割とすぐ実装できて、
開始1時間ほどでSubmit。


残り時間が少ないので1000点問題は解ける気がしなかったが、
一応少しは考えてみた。
p1 .. pn が与えられたとき、
k1^p1, .. , kn^pn (k>=2, i!=j => ki!=kj)
をすべて約数に持つ最小の整数を求めよ、というもの。
たとえば、{2,2,2} なら 答えは 36。
(2^2, 3^2, 6^2 と選んだときが最小)
制約条件は、n=10までだということと、答えはlong longに収まるということ。
時間まで考えるも、うまい方法はさっぱり思いつかず。
DFSで間に合っちゃうのかなぁ、とか思ったり思わなかったり。


というわけで、Coding Phaseが終了。
続いてChallenge Phase。
ほかの人のコードを見てみるが…。
ぜんぜん間違いが見つからない。
さすがにRound2ともなるとあからさまな間違いをやらかす人はいないのか。
それから大体全員分のコードを見るも、結局おかしいところは見つからず。


程なくしてシステムテスト
システムテスト前の順位が120位ぐらいだったので、
上位が落ちればどうなのかなぁ、といったところ。
さすがに参加者が少ないので、あっという間にシステムテストが終わり、結果が出た。
1000点問題そもそもSubmitしている人が20人ぐらいしかいなかったが、
最終的に通ってる人は2人しかいなかった。
やっぱりとんでもなく難しい問題だったんだなぁ。
で、私はというと…。300点が落ちてた…。
どんな入力で落ちてたかというと、
{".."}というような、プレイヤーもゴールもないような入力だった。
こういう場合は放っておいてもうまくいくと思い込んでいたが、
どうもだめだったようだ。サブミットする前に
プレイヤーがいなければはじいておこうかとも思ったのだが、
プレイヤーがなくて、ゴールだけあるやつがうまくいっていたので、
大丈夫なのかなぁと思い込んでしまっていた。
ああ、だめだ。


しかし、300点問題が通っていれば得点は430ほどになり、
大体90位で通過していたことになる。
惜しかった。かなり悔しい。
とりあえず今回の教訓は、フェイルセーフに実装しろ、ということだ。
今回はプレイヤーがないときにはじいていれば通っていたんだから。