ベスパリブ

プログラミングを主とした日記・備忘録です。ベスパ持ってないです。

estie プログラミングコンテスト2022(AtCoder Heuristic Contest 014)の参加記録

はじめに

atcoder.jp

開催期間:2022-09-17(土) 15:00 ~ 2022-10-01(土) 19:00 の2週間

  • AHCのコツ(メモ)
    • 評価関数から考察する(スコアを伸ばすにはどうすればいいか?)
    • ビジュアライザを色々試して考察する
    • まずは初期解を提出する
    • 制約から考察する

方針1:短い辺の四角形を優先的に作る

評価関数を眺めて、重心から遠い点を作るか、点をとにかくたくさん作ると良さそうだと予想した。

ビジュアライザをポチポチしてて思ったこととして、重心から遠い点を作ろうとして辺の長い四角形を先に作ってしまうと、その辺が邪魔して作れる点の数が減ってしまうことに気づいた。

なので、まずは辺の長さ1の四角形を作るようにして、徐々に辺の長さを伸ばすようにすればたくさんの点を作れそうなので、そうすることにした。

そのような方針で、とにかく小さい四角形を作りまくるナイーブな実装をした(たくさんバグらせて大変だった)。

最初は辺の長さは1で、徐々に大きくする。

提出コード:https://atcoder.jp/contests/ahc014/submissions/35003739

スコア:32,575,448

方針2:乱択 & 試行回数を増やす

山登り法を実装したいと思ったのだけど、どう実装したものか悩む。

出力は、新しく印の付いた点を作る履歴を出力している。この履歴の適当な区間 [start, end] をより良いスコアに差し替える山登り法(個人的に履歴差し替え法と呼んでいる)をしたいと思ったのだが、差し替えるために削除する印のついた点が、[start, end] の区間以外で利用されていると削除するわけにはいかないので、削除してはいけない点を保持しないといけない。なかなか面倒くさそうだし、削除してはいけない点は多そうなので、差し替えが成功するパターンはあんまりなさそうで、スコアが良くなるような気があまりしなかった。なので、別の方法がないかなあなどと考える。

手慰みの新方針として、方針1の実装で、小さい四角形を探索する方向を2パターン作ってより良いスコアのほうを採用することをすると、スコアが1000000程度伸びた。

なので、結構適当に乱択してもスコアが伸びるのではないかと予想した。どの程度伸びるか知りたかったので、そのような実装をした。

  • 実装概要
    • 作れる四角形の辺の長さは1にする。
    • 始点となる印の付いた点はランダムに決める
    • 始点となる点を決めたら、新しく点を作るためにどの方向を走査するかはランダムに決める
      • 新しく点を作れたら、新しく作った点を始点に再度探索をする。
      • この方法を3回ほど試して、スコアの上がり幅が大きいものを採用する
    • 新しい点を作れなくなくなったら、辺の長さを増やす。
    • 辺の長さがNかつ、新しい点を作れなくなったら終了。制限時間ギリギリになっても終了。
    • 制限時間に余裕があるなら、上記を制限時間いっぱい繰り返す。

5秒の制限時間いっぱい試行する。

提出コード:https://atcoder.jp/contests/ahc014/submissions/35038824

スコア:37,345,575

テストケースをいろいろ試して気づいたこと

  • 辺が長い四角形を優先的に作るよりも、辺が短い四角形を優先的に作ったほうが、スコアが良いことが多かった
  • テストケース "0002.txt" を見ると、初期状態が四角形に見える。この四角形を大きくできるかがスコアを良くするコツか?
    • 外側(または内側?)の点から優先的に処理したら良いかも

方針3:ビームサーチ

ビームサーチの結果。109秒かかった。

ビームサーチを実装したのだけど、TLEするし、ローカルで時間無制限に処理させても方針2と大してスコアが変わらなかった。

ビーム幅10でもTLEする始末。なんか実装間違えてる?

全然無理そうだったのでこの方針は却下した。

方針4:内側と外側で処理を分ける

入力の制約

上記の入力の制約により、初期状態は点は中心に集まっている。

新しい点を作るとき、外側に点を作れた方がスコアは高くなるはず。

外側に点を作れそうなら優先的に作り、作れないなら内側に点を作り、その後また外側に点を作れないか試行する。。。という風にすればできるだけ外側に点が作れてスコアが伸びるはず。

と思って実装したが、思いの外全然伸びなかった。

おわり

結局、方針2を高速化して試行回数を増やした乱択が最終提出となった。

最も良いスコアで 37,365,502 だった。40M超えたかったのだが…

最終提出コード:https://atcoder.jp/contests/ahc014/submissions/35326925

A-Final スコア:1,509,848,532

順位:215

解説(https://www.youtube.com/watch?v=eddDPITjzDc)を見ると、焼きなましで高いスコアが出るとのこと。まず初期解を求めて、そのあと適当に削除する点を決めたら、その点に依存している点もすべて削除して、スコアが上がるように作り直すと良いらしい。

方針2で山登りを諦めたのが敗因か。諦めない心が足りなかった。

1位のスコアは70Mを超えてた。うーん遠すぎる。