0.はじめに
トヨタ自動車プログラミングコンテスト2023#6(AHC026)に参加したので、やったこと/コンテスト中に考えたことを振り返ってみようと思います。前回のトヨタコンでは青パフォを出していたのでまあまあ期待しており、気合は十分。早速見ていきましょう!
1.問題を見て方針を探る
重要そうな条件として、
- 箱を取り除く順番が決まっている
があるため、焼きなまし系は厳しそう。ということで貪欲ベースに決定。
2.とりあえず正の得点を得る
次に取り出す箱(=残っている箱の中で最小のもの)をiとして、iが山の一番上にあれば無条件で取り除いて良さそう。
iが山の途中にあった場合、iより上の塊を別の山に動かさないといけないが、とりあえず(iがある山以外で)ランダムに選んで移動させ、山の一番上になったiを取り除く。
提出してみたところ、1216354点。30分弱しか経過しておらずまだ順位を気にする段階ではないのでこの解法を育てることに集中する。
3.時間いっぱい回してみる
この解法だと一回悪い移動をするとそれが点数に直接響いてしまうので、時間いっぱい繰り返し、一番よかったものを最後に出力してみる。
また、箱がなくなった山(山とは)を記録し、優先的に移動先にする工夫もしてみる。
提出し、1295764点を得る。少し伸びたが、やはり解法の中身を改良しないと上位には近づけなさそう。この時点で約1時間経過。
4.ランダム移動先を工夫する
具体的にランダム移動先について考えてみると、i+1やi+2がある山に移動させてしまうと次の移動で動かす量が増えて損、ということに気づく。そこで移動先をi+1~i+5がない山の中からランダムに選んでみる。
手元で動かしてみるとseed0で8100→8800くらいに伸びたため、期待を込めて提出。
結果は1343716点で223位/498人、かなり伸びてテンションが上がる。
5.ランダム移動を小分けにする
移動させる塊の中に比較的小さい数(i+3とか)が入っていたらそれを山の上に露出させておけば数回後で移動しなくてもよくなり得だと思い、
- iより上の塊の中で最小のものをjとする
- iより上の塊を、jより上の塊とj以下の塊に分ける
- 上の塊をランダム移動→下の塊をランダム移動
- jは確実に山の上に露出する
とする。勿論移動先はi+1~i+5が含まれない山の中から選ぶ。
ということで提出。
結果は1366399点で160位。まさかここまで伸びるとは。
6.その後
実は前日に徹夜しており、かなり眠かったため改良案が思いつかず寝落ちを決断。ここで撤退することにした。
7.最終結果
結局341位まで落ちてフィニッシュ。
Twitterで周りの反応を見てみると1356657点の貪欲の人が多かったらしく、ランダム移動が功を奏していたらしい。また、1343716→1366399で一気に伸びたのもその人たちを(知らぬうちに)追い越していたかららしい。
一応seed0で9115点のビジュアライザを貼っておきます
上位の人たちは各山をソートしていたらしく、かなり衝撃を受けた。が、よく考えてみたら
- 塊を移動させるのを小分けにしても労力は変わらない
- 塊を小分けにしまくれば(昇順になっている塊ごとに動かせば)ソートに近くなる
ということで、自分の解法からでも到達できそうだったことに気づく。後で自分でも実装してみようと思う。
8.反省と感想
- 前日に徹夜をしない(自戒)
- 乱択要素を入れたのは良かった
- 複数ケースで実験(今回はseed0でしか実験していなかった)
- 提出ごとに順位表のスクショを撮っておく(最初の2回は撮り忘れていた)