ACM/ICPC Domestic Contest 2010
自分に出来る最大のパフォーマンスを発揮したのだろうとは思うけれど、それでも悔しいものは悔しいのです。
Before Contest
- ぽつぽつと雨が降る程度の天気。
- ここ5年、国内予選の日には雨が降ってます。
- いつもは簡単な問題を解いてウォーミングアップするのですが、今年はスルー。
- ビジュアライザをちょっといじったりしてました。
- 毎年、ウォームアップの成績と本番の成績は反比例する傾向にあるので、ちょっと怖くなったというのもあったりなかったり。
- 私が寝坊したせいというのもあったりなかったり。
- 模擬予選と同じ方針で行こう、と確認してコンテスト開始。
Problem A: 角角画伯,かく悩みき
- 印刷した問題文を@romanchuに届けるときにちょっと読んで、「いつもより文体柔らかいなぁ、変わったなぁ」とか思ったり。
- ちょっと嵌ってたみたいだけど、すぐにCorrect.
Problem C: ポロック予想
- 読んだ。
- 典型的なコイン両替問題にしか見えない。
- 模擬予選の C を解いたとき「本番はこんなに簡単なはずがないよなぁ」と思ったのですが、まさかもっと簡単になるとは。
- 典型的なコイン両替問題にしか見えない。
- A の裏で B を読んだ @iakasT と会議。
- どう見ても C の方が簡単そうだ。こっち先に書いていいよね。
- A が通ったので書き始める。
- 書いた。滅茶苦茶な値出てきた。
- って、最小枚数じゃなくて表し方の総数を求めてた!ばか!
- 一瞬で直した。sample出てきた。
- Correct.
Problem B: 迷図と命ず
- C 解いてる間に紙の上に擬似コード書いてもらってた甲斐あって、@iakasTがあっという間にCorrect.
Problem D: ぐらぐら
- 面倒臭いけど書くだけらしい。@romanchuに頑張ってもらうことにした。
Problem E: 最強の呪文
- 文字列連結と辞書順最小の組み合わせって何か危険な臭いがする。
- そう簡単に Bellman-Ford の負閉路検出には持ち込めないような気がするんだけど...。
- なんとなく writer はあの人なんだろうなとか思ったりする。
- 相変わらずいい問題作るなぁ。解ける気がしない...。
- ...
- ...この嫌な気持ちをはっきりと言葉に表してみたい。
- ...
- ノード n を除く全てのノードについて、そこをゴールとしたときの解が分かったとしても、それを使ってノード n の解を求めることが出来ない!
- 例えば、(0 -> 1, "abc"), (0 -> 1, "abca"), (1 -> 2, "d") という3本の辺があったとする。
- ノード 1 で終わる最適解は "abca" ではなく "abc"。
- にもかかわらずノード 2 で終わる最適解は "abca" + "d" になっている!
- つまり、dp[n] := n で終わる最小の文字列 を求める解法は不可能!
- じゃあどうしよう。
- とりあえず、dp[n][l] := n で終わる長さ l の最小の文字列 みたいなことは出来るはずだ。
- あとは、無限に長い文字列が作れる場合を検出すればOK.
- とても長い文字列が作れたら、きっと無限に長く出来るに違いない。
- スーパー嘘仮定タイム!!!
- 辞書順最初の文字列を作るとき、同じ辺を2回以上通らない!
- 全ての辺の文字列長の総和 を越える辞書順最初の文字列が見つかったら、無限に長く出来る!
- すると dp[40][400*6+いくつか] でどうにか間に合う!
- 辞書順最初の文字列を作るとき、同じ辺を2回以上通らない!
- ...で、この嘘仮定って本当?
- 普段なら信じて突っ込むところだけど、よりにもよって国内予選でそれはしたくない。
- どうしよう...。
- ...
- あ。
- 同じ辺を2回通るということは (A)(S)(B)(S)(C) 見たいな文字列が出来るということで。
- (S)(B) < (S)(C) ならば、 (A)(S)(B)(S)(B)(S)(C), (A)(S)(B)(S)(B)(S)(B)(S)(C), ... って無限に長く出来るし、
- (S)(B) >= (S)(C) ならば、 (S)(B) を取り除いて (A)(S)(C) としたほうが小さい。
- どっちにしろ解にならない!
- 嘘は本当になりました!やった!
- @romanchu のヘルプに入れるように D の問題文を読みつつ、ペアプロしながら@iakasTに実装してもらう。
- sample出てきた!submit!
- Wrong Answer...
- ...
- どこがおかしいんだろう。アルゴリズムは間違ってないはずだ...。
- dp[n][(全ての辺の文字列長の総和) + 100] を計算してるのだけど、怪しいのはこの適当に決め打った 100 ぐらいしか...。
- ...マズい!
- 40ノードを全力で使えば、長さ240ぐらいの閉路が作れてしまう!
- +400 ぐらいにしてジャッジデータ食わせてみる。1ケースだけ答え変わった!
- ついでに +1000 とかも試してみる。もう変わらない。
- 今度こそ行けるはずだ!submit!
- Correct!
Problem D: ぐらぐら
- トリプロ開始。
- ほとんどのケースは出てきたけど、重心の計算がおかしくて1ケースだけ合わないらしい。
- もしかして重心の定義を勘違いしているのでは?と思って、別の解釈で重心を手計算してみる。
- 計算し終わる前に、@iakasTが今の解釈でも正しく出るはずと結論付けた。
- そうこうしているうちにバグも見つかって潰れた。
- 待望のCorrect!
- @romanchuに強実装を投げておくと、そのうちきっちり解いてくれるのでチームメイトとしては気が楽です。
Problem F: 古い記憶
- あと45分ぐらい残ってる。諦めるには早すぎるけど、全然思い浮かばない...。
- さすがに全探索は間に合わないだろう。編集距離 d 以下を全列挙ぐらいならできそうだけど。
- 最低 13 文字という条件が露骨に怪しい。
- 「最小の入力サイズにちゃんと意味がある問題って美しいよね」みたいな事を偉い人が仰ってたのを思い出した。
- やっぱり writer の顔が透けて見える。
- 40 (テキスト長) - 13 = 27.
- 使用できる文字も大文字アルファベットと . の 27種。
- よく見たら問題文の冒頭も 西暦4'27'2年。
- これらは何らかの複線なのでは!?
- 「最小の入力サイズにちゃんと意味がある問題って美しいよね」みたいな事を偉い人が仰ってたのを思い出した。
- とか言ったところで解法は見えない...。
- ...
- あれ、よく見たら「全てのピースは同じ長さである」とか書いてある!
- これはすっごく使えそうな気がするというか解法見えた?
- 整理しつつチームメイトに説明してみよう。
- 編集距離 d 以下の文字列を全列挙する。
- これは愚直にやる。
- 挿入・削除・置換がそれぞれ (40*27), (40), (40*27) 通りぐらいあるので、1回でざっと 2,400 分岐。
- d <= 2 なのでおよそ 2,4002個。全列挙できなくも無い。
- 挿入・削除・置換がそれぞれ (40*27), (40), (40*27) 通りぐらいあるので、1回でざっと 2,400 分岐。
- これは愚直にやる。
- 全列挙したそれぞれの文字列について、作成可能かどうか線形時間で判定する。
- 残り時間は35分。書けるか?いや書くしかない!
- がりがりがりがり。
- 全列挙のところ、string使わずにchar配列で丁寧にやらないと遅くなりそうだけど、そんな悠長なことを言ってる時間は無い。
- 書けた。ハッシュの計算がちょっと違う。覆えるかの判定もちょっと怪しい。直した。
- まだ作られない文字列がある。
- sample2つ目の ".ABRACADABRA.ABRACADABRA." が出てこない。
- 覆えるか判定するルーチンに強引に放り込む。あれ、出来てる?
- sample2つ目の ".ABRACADABRA.ABRACADABRA." が出てこない。
- @romanchu「全列挙するときの枝刈りで刈りすぎてない?」
- コメントアウトしてみた。sampleの上3ケース出てきた!
- 4ケース目はしばらくお時間をいただいております。
- コメントアウトしてみた。sampleの上3ケース出てきた!
- しかし時計はもう 19:32.
- リロードしてみる。終わってた...。
Result
- 5AC, 20720sec. 5th place.
- 合宿には行けそう。目標は達成しました。
- F が間に合わなかったのが何とも悔しい。
- @iakasT が後で試したところによると、ジャッジ入力は14分ぐらいで出てきたらしい。
- 定数倍の高速化の余地があるコードだったので、頑張れば半分ぐらいにはなるかも。
- もっと時間があれば...とは思うのだけど、誰も無駄な行動を取ってはいなかった。
- つまりは実力が足りないのでしょうなぁ。
- @iakasT が後で試したところによると、ジャッジ入力は14分ぐらいで出てきたらしい。
Timestamp
- 出力ファイルのタイムスタンプ (≒ 正解した時刻) の晒し上げ。
bash-3.2$ ls -la {A,B,C,D,E}.out
-rw-r--r-- 1 (username) (groupname) 250 Jul 2 16:46 A.out
-rw-r--r-- 1 (username) (groupname) 254 Jul 2 17:05 B.out
-rw-r--r-- 1 (username) (groupname) 820 Jul 2 16:54 C.out
-rw-r--r-- 1 (username) (groupname) 396 Jul 2 18:40 D.out
-rw-r--r-- 1 (username) (groupname) 4243 Jul 2 18:27 E.out
- A, C, B, E, D の順番。
- アルファベット無視しまくりだけど、この順番で解いたチームは多いのでは。