TopCoderOpen 2011 Marathon Roun2

今回は頑張りが足りなかったです。最終順位はおそらく50位ぐらいですが、実は通過の100位以内も結構危なかった。
以下、参加したときのメモ。特に纏めてはいないのでぐちゃぐちゃです。CodeChefのJune Long Contestにも参加してたので、それも混じってます。

  • 2011・6・1

19:37
とりあえずCodeChefのCLONEを解いてる。これは楽に解けそう。
21:07
やっとCLONEを通した。最後に%modをするのを忘れて何回かWAを食らった。一番乗りでちょっと嬉しい。
11:52
CTEAMSを送信。pythonでかくよりCで書いたほうが楽だったかも。しかもRAをくらってる。
22:04
訳が分からないが、最初のN=input()でRuntimeErrorを食らってるらしい。謎だ。
22:16
N=int(raw_input())にしたら通った。いくらなんでも謎過ぎる。

疲れたのでちょっと休憩。

  • 2011・6・2

1:04
Maximal Score Pathをサブミット。無事一発で通過。これで三問。

2:17
marathon matchの問題。第一印象。幾何か・・・。
sizeの定義が書いてない気がする・・・。面積のことでいいのだろうか。
面積だとしたら、あまり辺数の多い多角形を作っても仕方ない。とりあえずは正三角形を作るべき?
得点が相対性なのがちょっと不満。そこそこ奥が深そうなので一位続出はないと信じたい。テストケースの数を増やすかもしれないし。

2:22
どうやって正三角形を探索しよう?頂点数5000は結構厳しい。

2:23
test Case Generationが結構ややこしそう。実際の図をみてもかなり特徴的な分布という感じがする。

2:27
半径1とすると三角形より四角形のほうが有利っぽい。
三角形 ルート3/2=0.4380 正方形1/2=0.50...

2:51
正方形の探索は、誤差を気にしなければOrder(P^2)で終わりそう。

3:00
眠くなってきたので、適当に何か実装、送信して、とりあえず寝よう。

4:01
区間分割して、正方形を作るのが妥当な作戦?

11:20
起床。得点の予想つかないけど、とりあえず組んでみるか。今回の問題はむずい・・・。100位以内も実は少し怖い。

  • 2011・6・3

2:18
SRMに参加してた。そろそろ、今日寝るまでに、何か送信しておかないとずるずる行ってまずい気がする。

3:15
javaのsubprocessとして実行すると、デバッグしにくいので、ファイルに書き出すことに。

4:09
choosePolygonsを呼び出しただけでsegmentaton faultを引き起こす謎のバグが発生。原因が分からなくてどうしようもない。

4:28
原因が分かった気がする。どうやら全然関係なさそうな部分に原因があるらしい。

10:44
起きた。

11:09
バグをなんとか修正して、やっと正のスコアが取れた。かなり出遅れてる感があるが大丈夫かな・・・。

11:13
16点ってどういうことだろう?いやな予感がする。

11:20
問題文よく見たら書いてた。・・・・。やばい。sizeは面積のことじゃなかった。頂点数の二乗らしい。これは非常にまずい。

11:21
かなり無駄に時間を過ごしてしまった。というか戦略を1から考え直すはめになった。

11:25
ふ、二日間ロスっただけだ。まだ、何とかなる。しかし、この得点の決め方だと、同点続出の可能性が確かにあるなあ。面積の方がよかった気がする。

11:26
やっぱり、すぐにプロトタイプを作らないと危険だということが分かった。恐ろしい・・・。

11:34
しかし、逆にちょっと考えやすい問題になったのは確かだ。基本的にでかい多角形から順に作っていけばいいだけの気がするし。

11:49
図形は小さくてもいいんだよなあ。それが一番重大な事実かもしれない。

15:42
Test Case Generationをちゃんと読んだ。螺旋状に点が配置されるのかと思ったらそんなことは全然無かった。
意図的に正多角形を作りやすくしてる感じ。

15:44
点が多い場合は中心位置を推理するのがまず重要になりそうだ。
中心の個数は最大5〜20個。

15:46
点の個数が50−499 と、500−5000で、色々パターンがあるので、場合わけをするべきかも。とりあえずは点の個数が多い場合の対策をするべき。

15:53
明確に円っぽい物が見えるときもあるけど、必ずしもそうではないなあ。

  • 6/4

00:34
ニコニコみて時間つぶしてた。何やってんだ・・・。

22:07
pygame極座標表示をしてみたり。
相当だらだら過ごしてるから、このままのペースでいくとまずい。

22:08
辺数を増やしたとき、実はradiiDiffってあんまり関係ない気がする。凸性と、sidesDiffの条件からradiiDiffは自然に大丈夫になるんじゃないかと。

22:09
実験してみないと分からないけど。

  • 6/6

00:41
中心決める方法はあんまりうまく行かなさそうなきがするなあ。

14:20
正多角形の位置の頂点で、一番近い点を選択するという、普通の方法を実装することにする。何故かこれを思いつくのに時間がかかった。

  • 6/8

4:30
あと一時間以内に方針を決めて、さらに1時間以内にsubmitしよう。

4:50
やりかた候補
完全にランダムに中心と半径を決める。
二点決めて、その中心と距離で半径を決める。
3点選んで中心と半径を決める。

  • 6/10

謎の雑務が終わったので、今から本気出して頑張る。とりあえず駄目コードで一回submitしている状態。
18.03点で146位。clock()関数があまりよく機能していないことに気付いて衝撃を受けている。これはまずいだろ。

  • 6/11

1:21
起きたので開始。

1:53
clock()関数で1秒で打ち切ったら、実行時間が3〜5秒ほど。なにこれ・・・。

2:21
clock()関数の代わりにgettimesofdayを使ったら、うまく行った。何か変な気がするけど、これで戦える。

2:48
timerをちゃんとセットして送信したら、28.03点。126位。

6:05
exampleの結果をメモ
112.0
928.0
8352.0
13040.0
864.0
8576.0
736.0
512.0
3968.0
208.0

これは二点選んで、それを対点とする正方形を探索し続ける作戦。


6:21
時間が<5のときは辺数6
>5のときは辺数4で
テスト

116.0
940.0
10992.0
17872.0
916.0
9828.0
696.0
496.0
5292.0
200.0

逆にSCOREが落ちているケースもある。(3つのケース)。これは意外。

15:23
全く同じコードでテストしてみたら、結果が不安定。これはちょっとやる気をなくす。

  • 6/12

0:29
正三角形も真面目にサーチしたら、それだけで割りとましな点数になりそう。

163.0
1424.0
11754.0
18614.0
1225.0
11049.0
1118.0
762.0
5626.0
288.0

全て上昇した。

送信してみる。今は順位126->134らしい。

00:34
三回目のsubmit。57.66点ゲット。134->70位。100位以内に入ったのがなんとなく安心材料。まだまだ油断できないけど。

00:39
これ以上、先に進める場合は、実行時間によって最善の選択肢が変化する可能性があるので、最適化を先に行っておくほうがいいかもしれない。

1:57
正多角形を作ろうとする試みを何回行っているかメモするようにした。
グローバル変数をinfoを作った。あまりグローバル変数を使いたくないが仕方ない。

2:30
何気なく結果を見てたけど、どう考えても処理に時間がかかりすぎている。例えば最初の5秒で、7480のバケットしか
調べられていない。多分bucketのサイズが大きくなりすぎている。(ひとつのバケットに点が入りすぎている)のが原因と思われる。
2:50
変数がよほど大きくならない限りは、最も近い点を調べる作戦に大きな問題があるとは思われない。

3:16
ボロノイ図的なものをつくるのがいいかな。

3:29
時間を増やしても、SCOREの上昇は多少に留まる。もう点数は限界が近いかな。

12:31
起きた。なんかぼろぼろだ。

19:00
一応profileをとったらsq()に時間がかかってるので、やっぱりbucket大きすぎ説は正しい。

19:01
二度寝してしまったので、

21:22
ボロノイ図作ってみたけど、まだ速度が甘いかな。

21:23
と思って、何も変更せずにもう一度送信してみたら、探索量が増えてる。謎。さっきたまたま遅かっただけか・・・。

23:34
探索量があまりに不安定だし、example testでも似たような感じだから、なにかおかしなことが起きてそうだ。調べたほうがいい。
177.0
1294.0
11077.0
17272.0
1117.0
10746.0
1064.0
675.0
5225.0
288.0

  • 6/13

ボロノイ的なことをしたら、余計に得点が下がってしまったが、これは多分、近距離候補の10点をを全て使い切ってしまっているため。対策はどうしよう・・・。

0:38
きれいなやり方ではないけど、残りのpointの数が減ったら、全探索に切り替えるという手もある。

3:44
次の手はどう打つべきか・・・。ボロノイを利用する作戦はあまりうまく行ってないようにみてる。色々なサイズのbucketを用意するのがいい気がする。

5:38
一時間以内に次の作戦を決める。

6:27
bucket法を拡張するのが妥当という結論に落ち着いた。

6:28
点の数が多い場合は思った以上に煮詰まっているんじゃないかという気がしてきた。

7:37
何か適当に改良してexample testしてみた。
177.0
1452.0
13136.0
21312.0
1272.0
12207.0
1108.0
821.0
6169.0
299.0

ローカルよりいい点数が出やすいようだ。これはちょっとやりにくい・・・。

7:39
submitしてみるか・・・。現在54.29点で83位。これは4回目のsubmit。

7:43
結果は65.64点で54位だった。土日を乗り切ったから多分、もう100以内からは多分落ちない。
前日ラッシュの可能性も無いわけではないけど。

8:11
しまった。よく考えたら -O2オプションつけるの忘れてた。そりゃローカルの挙動がおかしくなって当然だ。あほだ・・・。

9:46
頂点数が多い場合は遅かれ早かれ、最適化ゲーになる可能性が高い。とりあえず、まずは頂点数<500の対策を先にやっておこう。

17:29
まず、最後の三角形の選択の改良をどうにかしないと。

  • 6/14

22:22
もう残り時間が少ない。結局だらするだけで時間が過ぎ去ってしまっているので、今からは本気でやる。
今は70位なので非常に危ない。

まず、方針はひとつに絞ってやるべき。あんまりだらだらやってると、予選落ちもありうる。
現在は正多角形を、選んだら、それで固定してその点は使わないアルゴリズムになっている。
長所は、使われていない点による正多角形のみを、検索しているので効率がよい。
短所は、一般に解は最適とは限らない。
この短所を克服すれば多少の点数アップが望めると思われる。
というより、これをいかに行うかが高得点化の鍵だと思われる。
そのためには正多角形をリストアップしてから、どの多角形を使うか決める方法がいい。
ただし、この戦略のせいで、長所が死んでしまうと、逆に点数が落ちかねないからそれは気をつける必要がある。
もうひとつ、今までは、時間が来たら探索を終了していた。
正多角形をリストアップしてから、どれを使うかきめる方法をとったとき、
正多角形をきめるステップの実行時間を正しく評価できていないと、タイムオーバーの危険があったりで、
有効に計算時間を使うのが難しい。正多角形を見つけるたびに動的に使う多角形リストを変化させれば、単に時間いっぱい計算すればいいことになって、有効に時間を使える。どっちの作戦がいいかは分からない。
安全なのは後者なので、後者の作戦でいくべきだろうか?残りの時間は少ないので。
後者の作戦で行くとして、どのようにアルゴリズムを設計するべきだろう?
まず、辺数の大きいほうから決定することに大きな問題はない気がする。大きな辺数の多角形を犠牲にして逆に点数を稼げるパターンも無いわけではないけど、割合としては少ないだろう。より上位を目指すならそうするべきだが、とりあえず後回し。
で、動的に多角形リストを更新ってどうやってやるんだ?

22:49
ちょっと紙に書いて考える。いつもこのまま考えてる間に堕落するパターンなので、23:10までに切り上げて、状況を整理する。23:00
前回のR2と同じようにラグランジュ緩和法をつかうのはひとつの手だ。多分前回よりうまく行きやすい状況だとは思う。
でも、正直なんでうまくいってるのか自分でもあまり理解していない方法なので、あまり使いたくはない。というのがある。

23:03
しかし、これはどうみても重みつきset packing problemだよなあ。納得はいかないけど、ラグランジュ緩和法をつかうのは仕方ない気がしてきた。

23:09
packing problemとして定式化する方法を詰めてみる。一つ目の問題点は、使われていない点による正多角形の検索を放棄していること。

23:11
現在の正多角形のリストアップ方法は、
1:ランダムに二点を選ぶ
2:その二点を対点とする正多角形を検索する。
3:そのさい頂点は、理想の位置に最も近い点で、まだ使われていない点を検索する。
という方法をとっている。

23:18
最悪、前のアルゴリズムを繰り返しまくる作戦でもそこまで大きな問題はない気がする。

23:23
とりあえず、ラグランジュ緩和的なことをすることで、方針は決定した。よく考えればこれは非常にいい方法だという気がしてくる。

23:25
まだ一時間ほどしか考えてないが疲れた。とりあえず後一時間ほどは双対的な方法のやり方を自分なりに整理する。

  • 6/15

5:39
単体法を今から実装する。

単体法は放棄しました。

22:38
メモをとる余裕もないぐらいあせりまくってます。順位は110位。やばい。
example testの結果。

179.0
1559.0
13339.0
21514.0
1333.0
12434.0
1158.0
830.0
6400.0
328.0

一応全て点数が上がったから何とかなるかな。何とかなってほしい。

22:41
最適化に取り組む。

23:53
送信した。71.23点。50位。

example 15のresult
179.0
1575.0
14283.0
24640.0
1262.0
12240.0
1169.0
853.0
7120.0
328.0