競プロ始めました-kaede2020-

競技プログラミング初心者向けのブログです

THIRD プログラミングコンテスト2023(AtCoder Heuristic Contest 030)参加記

0.はじめに

はじめまして、もしくはお久しぶりです。競プロ歴5年目突入のかえでです。

今回は、 THIRD プログラミングコンテスト2023(AtCoder Heuristic Contest 030)に参加しました。開催期間は2024年2月9日(金)19:00から2024年2月19(月)19:00までの11日間の長期コンテストでした。これまでは土曜始まりの日曜終了が多かったのですが、今年は金曜の夜から月曜の夜までの開催になりました。AWTFのヒューリスティック部門ができたため、海外勢のことを考えての時間変更のようです。

時間が長くなったのはうれしいけれども、月曜日には仕事があります。最終日の月曜日に自分が何を考えているのかは気になります。今回は日曜日までのつもりで参加する予定ですが、次からは有休を取りたいと思うようになるのかもしれません。

さて、今回はどんな問題なのでしょうか。この参加記を読んで私といっしょにヒューリスティック問題を解く楽しみを感じてもらえたらうれしいです。そして、AHCの解説には誰でも解法を載せることができるので、ぜひどんな解き方をしたのか書いてもらえたらうれしいです。

それでは始めましょう。

1.問題文を読む

仕事帰りに問題文を読みました。

atcoder.jp

  • N×Nマスの島がある
  • M個の油田がある
  • 各油田は連結している
  • 1マスを選択するとそのマスが油田かどうか明らかになる(コスト1)
  • 2マス以上(kマス)を選択するとコストは1/√kと低くなるが、事前に与えられたパラメータ  を用いて抽出しなおした値となり、正しい情報からずれが生じる
  • 油田のマスを全て当てると終了する。間違っていたときはコスト1を払って継続する。
  • 少ないコストで全ての油田マスを当てる

    2マス以上選択した場合の占いの値

うーん、2マス以上選択したとき、どのような値が返されるのか、いまいちピンときません。ビジュアライザを見ることにします。

2.ビジュアライザを見る

問題文の「例を見る」からリンク先のビジュアライザを開きます。

問題文の下の方にある「例を見る」リンク

例を見るからビジュアライザを実行する

ビジュアライザを再生してみると、島を9分割して、最初に1回調べ、その後は1マスずつ順番に調べている様子がわかりました。

Score = 176800000

Cost = 176.800000 (+0.000000)

ということがわかります。

PythonのサンプルコードがついているのでC++に書き直します。seed0を実行してみます。

あれ?ずれている。

問題文をよく読んでいないので何が起こっているのかよくわかっていません。このサンプルコードは正解を出していないコードなのかということだけがわかりました。

サンプルコードのビジュアライザ

問題文中の「ツールで用いられる入出力ファイルの仕様」を読みました。ダウンロードしたseedファイルには追加の情報が与えられていました。

その部分の入力読み込みを書き足します。

サンプルコードの正しいビジュアライザ

今度は正しく正解を出せました。

Score = 225000000

Cost = 225.000000 (+0.000000)

が出るようです。サンプルコードの得点は 225000000、「例を見る」のコードは176800000点だったので、「例を見る」のコードのように分割するだけでも得点が上がりそうです。

現在の時刻は22時30分。順位表を見ると、saharanさんの得点がずば抜けていました。

3時間半経過後の順位表トップ


今サンプルコードを提出すると、13,722,735,956点が出るようです。

とりあえず明日はサンプルコードの改善を行いたいと思います。疲れているので今日はもう寝ることにします。

3.最初の提出

翌日です。2024年2月10日土曜日の夜です。昨晩から腹痛に悩まされ、一日寝込んでいました。食中毒のような気がします。やっと少し体調が良くなってきたので、AHCに取り組むことにしました。順位表を見ます。トップはsimanさん、提出者は497人です。サンプルコードの得点は8,829,947,917にまで下がっています。

2/10 18:40現在の順位表のトップ

サンプルコードをローカル用に書き替えます。サンプルコードを少しだけ改善して、全部の油田が見つかったら終了するようにします。seed0のビジュアライザはこんな感じです。

seed0のビジュアライザ 全部の油田が見つかったら終了する

100テストケースのスコア平均がサンプルコードの88%に減少したので、順位表の相対スコアから推測すると、サンプルコードの提出は8,128,182,231、全部の油田が見つかったら終了するようにすると8,937,279,834になりそうです。

提出します。

最初の提出 絶対スコア:11411000000

最初の提出 相対スコア:8,937,279,834 190位/514人中

思った通りの相対スコアになりました。順位は514人中190位です。まだサンプルコードを提出しただけの人が大半のようです。

4.考察

日曜の朝です。体調もやっと回復したようです。よかった。

さて、今回の問題でいつもと違うことは、途中で何回も答えを出せることです。それも間違えたときのペナルティのコストが1ととても小さい(今は小さいと思っていますが、そのうち大きく感じるようになるのでしょうか)。だから、候補がある程度絞れたら、答えの出力を全通り試してみても良いのではないかと思っています。

今やろうと思っていることは油田の左上のマスを見つけること。

左上マスの定義(jが最小値のとき一番小さいi)

最初にマスが存在する範囲を調べておきます。油田の矩形が大きければ存在する範囲が小さいはずなので、そこの部分を調べていきます。点が見つかったら、油田の相対的な位置を調べて、1だったら合っていそう、0だったらこの油田ではないということがわかるはずです。

左上マスを起点として油田を重ね合わせる(seed0)

1個ずつ油田を決定してあげて、残りの油田の個数が少なくなれば、1個の油田の場所(左上のマス)がわかれば、調べなくても答えとして提出しても当たりそうな気がします。

その前に、ビジュアライザでseedを100個くらい眺めていたら、すかすかだな、と思いました。島の中で何もないところが多くあるので動ける範囲が大きく、自分のやり方が非効率な感じがしました。1マスずつ調べないで、3×3マスを最初に調べるだけでもスコアが良くなりそうだと思います。その場合、占いになって、正確な値ではなくなります。

一度に4マス調べたときと、1度に9マス調べたとき、epsによってどれくらい数値が悪化しそうかを計算してみます。調べるコストは4マスのときは1/√4=1/2。これに4を掛けてコスト2になるのかな。9マスのときは1/√9=1/3。コストが3なのかなと思います。

占いの結果

やってみます。ん、違いました。4を掛けたり9を掛ける必要はなく、4マスを調べるコストは1/2、9マスを調べるコストは1/3でした。

え、すごいコストが低い。

epsが小さければ必ず使った方が良さそうです。epsが大きいときが悩ましく見えるのですが、これ、絶対に判別できるやつだと思います。過去のAHCでもっとすごいのがあったので。というわけで使わないとダメそうだなと思います。

正しく使えると良いのですが。

そして今やっと気がついたのですが、ビジュアライザでは占いの結果であるResponseが出ます。9マス調べた結果は0。

おお!

seed0のビジュアライザ

eps0.2のとき、どんな値が出るかを試してみたいと思います。というか、ローカルで計算できるのではという気持ちになってきました。ダウンロードしたseedに、何か補正用の値が入っていた気がしています。

seed11で試します。全部0の7マスを調べると1が出ました。4マス、3マスにすると0と0でした。

ふむ。

適当ですが、epsが0.1までは9マス、それより上は4マス単位で調べてみようかと思います。

5.油田の基準の位置(左上)から油田位置を確定する

まずはローカルで占いの結果を出力する関数を書きます。

…と思ったのですが、左上マスから油田を推測する方を先に書きたいと思います。

盛大にバグらせつつも書きました。提出します。

絶対スコア 10933000000

相対スコア 8,440,031,085 222位/608人中

seed0のビジュアライザはこんな感じです。

seed0のビジュアライザ

やっぱり無駄な0が多いのが気になります。

あと、ここで入力の形式に合わせて左上をiが最小値のときの一番小さいjとします。

6.占いを使用する

4マス占いを入れてみます。responseが0なら調べた(1マスを調べて確定したことと同様に扱う)ことにしてとばすことにします。

提出します。

TLE

あれ?

相対スコアの得点も0(表示されず)です。

コードを見直すと、占い部分のクエリの出力を行っていませんでした。

修正します。またepsが0.05以下のときのみにします。今度は良さそうに見えましたが1個TLEしました。それでも相対スコアは提出前の得点7,512,742,471、順位245位から少し上がったようです。相対スコアは8,046,439,861、637人中227位になりました。

またもTLE

相対スコア:8,046,439,861 227位/637人中

ビジュアライザでは占い部分を赤で表示することにしました。現在の状況はこんな感じです。

Score = 49654701

Cost = 49.654701 (+0.000000)

seed0のビジュアライザ

この後はコードの入出力部分が煩雑なのでリファクタリングをしたいと思います。また、占いが間違っていたときにもう一度調べる部分を追加したいと思います。

7.実装が難しい

リファクタリングをしながら思ったのですが、処理が複雑でバグらせやすいなあと思います。やりたいと思っていることになかなかたどり着けません。

油田が重なっているときの処理がうまくいきません。

BFSを使って、周辺の油田を探します。100テストケースでエラーが出なくなったので提出します。結果は50ケース中4WA。絶対スコアは0点です。

4WA

それでも相対スコアは提出前の269位、7,337,645,941から699人中263位、7,550,993,446に少しだけ上がりました。

相対スコア:7,550,993,446 263位/699人中

そろそろ0時を過ぎるので寝ようかと思います。その前にもう1回だけ提出したいと思います。

おっと。

21WA

相対スコア:3,622,721,078 615位/700人中

続きは明日(厳密には今日)考えたいと思います。

7.バグらせて全消し(再度考察からスタート)

コンテスト4日目、2024年2月12日の朝です。今日は建国記念日の振替休日でお休みです。うれしい。

今日は金曜日

就業後AHC

姿勢は前傾

欲しいのは天啓

バグらせて全消し

祈る入青

さて、これはコンテスト初日の昼に書いたXのポストです。結構リズム良く書けたかなと思っていましたが、まさか本当になるとは。

昨日(厳密には今日)寝ながら考えたのですが、やっぱり自分の解法が問題とマッチしないなあと思いました。同じ形の油田が複数あることや、油田が重なっているところを処理するところが難しいので、1対1の対応をつけるのが難しく感じています。

それよりは油田を見つけた後で「調べた結果が矛盾しないよね」というチェックに使った方が良いように思います。

言いかえると、今回の問題は「適当に調べて見つけたらガンガン掘っていく」ということです。占いのコストが低いこと、間違った答えを提出しても挽回するチャンスがあることなどから、調べていないところを順に隈なく調べていくというのは何か違うなあと思うようになりました。

というわけで、コードをシンプルに書きなおすことにしました。

  • 占いは矩形で調べることにして、長方形の頂点のうちの左上と右下の座標を入れると、長方形に含まれる全ての格子点の座標を出力するものにする
  • 占いの結果を入れるデータ構造を用意する(推定のしかたがわからないので、あらためてbowwowforeachさんのAHC022のブログを読み直そうと思っています。後からリンクを入れる)
  • 占いの結果は重複する範囲に行ってもよい
  • 方法
    • 面積を半分に割っていき、ある程度油田が含まれる確率が高くなったらそのうちの1マスを油田が出るまで調べる
    • 1マスの油田が見つかったら、BFSで1マスずつ周囲を隈なく調べる
    • 最初の入力で与えられた油田マスの個数と合っていたら答えとして提出する
    • 油田の範囲が足りなかったら最初に戻り、別の場所を調べる

こんな感じでしょうか。再度取り組みたいと思います。

8.どんどん占って油田を見つけたらBFSをする

占いの使い方はあまりわからないのですが、とりあえず、常に半分の面積を調べて、残りは全体から占いの結果を入れるみたいな形で補完していきたいと思います。

(時間経過)

夜です。ブログを書くのを忘れていました。リファクタリングをして、7で書いた解法を実装していました。ほぼ全消し。

かなりきれいなコードになりました。関数名はchatGPTにどんな名前をつけるとよいかを教えてもらいながら書きました。ただ英単語だとピンとこないものがあって、そんなときはローマ字に置きかえました。

(時間経過)

やっと提出する形になりました。

久しぶりに提出します。久しぶりのACです。絶対スコアは7511060615点。相対スコアは7,534,055,086、806人中286位になりました。

絶対スコアはかなり減少しましたが、思ったほど順位は上がりません。提出前は706位だったので、それを思えば元に戻ってよかったと思います。

絶対スコア:7511060615

相対スコア:7,534,055,086 286位/806人中

今のseed0のビジュアライザはこんな感じです。色も変えてみました。

seed0のビジュアライザ Score = 83755508

ビジュアライザを見ていて思ったのですが、同じクエリを繰り返しているようです。epsの値が小さいときは結果が変わらなそうなので、同じクエリは省略するようにしたいと思います。あとやっぱりBFSは無駄が多そう?

やっと考察の段階に進めてホッとしました。

祝日だった月曜日もあと1時間で終わります。

9.全部の油田が見つかったかチェックを入れる

火曜日の朝です。お布団に入っても考察が止まらなくてなかなか眠れませんでした。格子状にある一定の間隔で掘ったらどうかとか、ライン上にある一定間隔で占いをして多そうなラインを調べるとか。最初の上端のマスを見つける方法も悪くなかったなあなどと思っているところです。

まずは昨日のコードの無駄な部分、全部見つかったのにまだ掘り続けている箇所があったので修正します。少しスコアが改善したので提出します。

絶対スコアは7134241673になり、少し良くなりました。相対スコアも良くなり、6,436,292,148になりました。順位は提出前の315位から271位に上がりました。提出者は827人にまで増えています。

絶対スコア:7134241673

相対スコア:6,436,292,148 271位/827人中

ところで、昨晩トップに大きな変動が起きました。eijirouさんが提出をして、1位になっています。そして、2位以下と大きくスコアを離しました。すごい。

順位表のトップ

何が起こっているのだろうと興味津々です。自分もがんばって改善を続けたいと思います。

10.ビジュアライザを見る

ビジュアライザを見ながら考察します。気になったものが見つかったので修正します。

  • 最後まで見つからなかったときにまだ調べていない全マスを順に調べるようにしていたが、左上から調べるのではなくランダムに変更した
  • 範囲を9マスに絞ったのにマスの候補が0になり、繰り返し同じ範囲の抽出を行っていた(2次元を1次元に変換するときのMAXサイズを間違えていたので修正)

100テストケースを試すと少し良くなっていたので提出します。

結果は絶対スコアは6822011720になりました。相対スコアは6,747,596,612になり、順位は提出前の270位から227位に上がりました。

自分にとってはほんの少しの改善で順位がぐっと上がって驚きました。

そうなんだ…。

相対スコアって未だによくわかりません。

絶対スコア:6822011720    

相対スコア:6,747,596,612 227位/828人中
11.一定間隔で調べてみる

余談ですが、この問題を読んだときに頭に浮かんだのは「ホルカ×トルカ」というメダルゲームでした。地下の見えない場所に眠った宝をコインで掘り進めるというゲームなのですが、その中にソナーという発掘サポートアイテムがあり、それを使うとどこに何があるかがわかるという効果があります。このゲームに一時はまっていたのを懐かしく思い出しました。

さて、油田がどこにあるかがわかるに越したことはないのですが、適当に掘ってもビジュアライザを見る限り、まあ見つかるかもといった気がしています。

なので、適当な間隔で、例えば5×5マスに1回中央を掘ってみるといったことをしても良いのではないかと思いました。油田が見つかればそこからBFSをすることにします。

油田の形と重ね合わせる最初の方法はその次に試したいと思います。

3×3と5×5と9×9をやってみましたがあまり変わりません。絶対スコアは少し悪くなっているでしょうか。相対スコアも提出をして確認します。3×3を提出しました。

絶対スコアが少し悪くなり、相対スコアも提出前の243位から249位に若干下がりました。

絶対スコア:6858000000

相対スコア:6,702,583,473 249位/850人中

提出した結果は予想した通りでした。

最初の重ね合わせのアイデアに戻りたいと思います。

左端と上端を見つけることを優先したいのですが、まずは横に1行ずつ見ていきたいと思います。

お風呂で考えていたのですが、周りから詰めていくと良いのかなと思います。上下左右、パズルで枠から埋めるのと同じとでもいえば良いでしょうか。とりあえず最初にやっていた上を合わせるコードを入れるようにしたいと思います。

12.グラフと考える(雑談)

寝ている間(実際はお布団に入ってから眠りにつくまでの時間)の考察です。油田は連結しているのでその形を判別するのにグラフを使えないかなあと思いました。グラフの同型判定のことを思い出しました。ABCに出題された問題があるように思いましたがどの問題だったかを思い出せません。過去のAHCでも同じことを考えたなあと思いブログを見返すとありました。HTTF2023予選(AHC016)です。問題はABC232のC問題です。Nが大きいと難しいようです。Nが8くらいまでならできそう。

ブログを読み返して、この回のAHCは本当に何もできなかったなあと思い返します。何もできないのにひたすら何かをしている姿が自分のことなのに健気で泣きそう。もしAHCを始めたけど全然わからなくてくじけそうな人がいたら読むと励まされるかもしれません。

HACK TO THE FUTURE 2023 予選(AtCoder Heuristic Contest 016)参加記 - 競プロ始めました-kaede2020-

13.重ね合わせる

制限時間は3秒あるので、素直に重ねてみたいと思います。BFSをするときには上下左右に広げますが、それを上と左に限定します。すると左上のマスにたどり着くのではないかと。そこを始点として重ね合わせを行いま

す。

田植え方式で掘っていき、油田に当たったら上と左に進めるだけ進みます。

seed0のビジュアライザ1

こんな感じ。

seed0のビジュアライザ2

ただ、これはたまたまうまくいっていますが、思っているのと違うなあというのもあり、考え中です。

seed2のビジュアライザ

ただ、この形を見て、別のことを考えました。左はこれまでの自分の方法です。今の左のコストは約93、右のコストは76です。あと8マスを見つけるのにコスト17をかけないで済めば、今より改善できます。これならできるかも。周りの0を掘るのを少しでもやめることができれば。

seed2のビジュアライザ
14.ついにひらめいたかもしれない

重ね合わせるときに何もない状態だと候補が多すぎると思ったので、格子状に穴をあけておくことにしました。すると油田を置く候補がそれぞれ58か所、61か所出てきました。多いなと思います。

あ、と思います。格子状の点を線にした方が良いのかもしれない。

100か所、98か所に増えました。

じゃあこれなら?

格子点と十字のラインを入れます。

48か所と46か所。

seed0で初期に掘る場所を試す(格子、十字、格子と十字)

斜めはどうだ。90か所と65か所。

斜め

どうして候補が減らないのでしょうか。

そう、1があるから動けてしまう。ということで1が出たら隣接する0が出るまで掘りたいなと思います。やっぱり。

お風呂に入ってきたら冷静になりました。候補が54か所って別に多くないな、と。

方針が決まりました。

  • 格子点を掘る
  • 候補を出す
  • 候補は占いをする
  • 確率的に油田マスがなさそうなところは候補から外す(この辺は考え中)
  • 候補が少ない油田、もしくは見ていないマスが少ないもの、もしくは油田マスが多そうなものから試す(この辺は考え中)
  • 実際に掘るとき、同じ番号の油田マスの中でどれから掘るのかも思案中
  • 予想が外れたら候補から外す
15.実装

実装してみたら、seed0の油田の置き場所候補がそれぞれ6個、8個でした。

seed0の置き場所候補

え、これ、多いのから調べたら1回で正解になります。

何だかわくわくしてきました。

残念ですが日付が変わりそうなので続きは明日にします。

と思ったのですが、その後30分程かけてコードを書きました。

油田候補を出して一番予測した油田数が多い置き場所を答えとして出し、ダメだったらランダムで埋めるという内容です。予測が当たった分だけ良いスコアを出せるかなあと考えました。

ドキドキしながらて出します。提出前の順位は284位。相対スコアは4,128,638,132です。提出していない間にだいぶ下がっています。

提出して早々にジャッジ結果がTLEに変わります。TLEが17個出て絶対スコアは0点、相対スコアは704,489,123、915人中744位になりました。思った以上に悪いスコアに残念だなあと思います。

100テストケースの結果もあまりよくなかったのでしょうがありません。

明日もう一度考えたいと思います。今度こそ本当にお休みなさい。

AC33、TLE17

提出後
16.落ち着いて考察をする

焦ってはいけないと自分に言い聞かせます。seed0のスコアは予想が当たって27206755点を出すことができていますが、これは判別が容易なseedだからです。1回で当たらなくても、少しずつ掘っていけばよいのです。BFSより良いスコアが出せれば良いのだから。TLEを解消する方法を考えたいと思います。

seed0のビジュアライザ Score = 27206755

seed1のビジュアライザを見ると、予測のための占いの回数が多いことに気がつきます。1マスずらすたびに占いをしていたからです。また、油田のサイズが小さいため、占いのコストもかさみます。候補が多いときに占いをするのは効率が悪く感じました。

重ね合わせながら、埋めていくことにしました。

うーん...。

絶対スコア:0(AC46,TLE4)

相対スコア:2,085,609,473

場合分けをしようと思います。

ビジュアライザを見ながら少しずつ修正します。実際に埋めてみる条件をepsによって変えてみました。100テストケースの結果は少し持ち直しました。

提出しますが、まだTLEが3つあり、得点は0点です。サンプルコードの相対スコアは2,293,731,454なので、それよりは良くなっているようです。

相対スコア:2,393,304,590 544位/948人中

Mが2以下のときでepsが0.1以下のときは埋めずに推測をするようにしました。

TLEがまだ2つあり、得点は0です。相対スコアはまた少し伸びました。

相対スコア:2.639.215.484 490位/948人中

そういえば、2があったときの対処をもう少し考えてもよいかもしれません。必ず端なので。

久しぶりにACしました。100テストケースで予測をしていましたが、過去のベストよりはかなり悪いスコアです。

だいぶ良くなりはしたものの、相対スコアを見ても2,51,040,103、957人中460位でした。

絶対スコア:8210454020

相対スコア:2,951,040,103 460位/957人中

過去のベストが今相対スコアでどのくらいかを知りたくなったので、2月13日朝のこれまでのベスト、絶対スコアが6822011720だったコードを出し直してみます。(「10.ビジュアライザを見る」で提出したものです。)

これまでのベストを再提出 318位/966人中

すると、相対スコアは966人中318位でした。やはり今でもこちらの方がだいぶ良いようです。なぜ、これが良いのかを考察して、改善してきたコードと合体させることができるといいなと思います。

17.過去ベストと今の比較

100テストケースで過去のベストと今のスコアを比較しました。一つ気がついたのは、Mが大きいときのテストケースが少ないことです。もう少しテストケースを増やしてみたいと思いますが、Mが大きくなったときのスコアが悪いようです。また、Nが大きいときもスコアが悪くなっていそうです。

過去のベストと今のスコアの比較(100テストケース)

考えていて思ったのは、Mが2でepsが小さいときは実際に掘る必要はなくて占いだけで良さそうです。逆にMが大きいときは実際に掘ることが必要になりそうです。

と、そこまで考えて、5×5マスくらいで区切って、その範囲にいくつあるかを占って、25で割った数をそのマスに予測として入れておき、その中の1つを掘って1が出たら残りのマスの予測が下がり、0が出たら残りのマスの予測が上がるみたいな更新を入れていくと良さそうだと思います。ある程度5×5マスの占いが信頼できるくらいまで何度か占っておきたいものです。とりあえずepsを100倍した数にしてみようかと思います。epsが0.01なら1回、0.2なら20回というように。コストはそれぞれ0.2、4かかりますが、そんなに悪くなさそうです。

5×5マスを実装中です。まだ途中なので続きは明日行いたいと思います。今回は本当に悪戦苦闘しています。

条件を変えて試しているところ
18.1000テストケースをまわす

5×5マスの予測はそれほど悪くなかったものの、自己ベストは越えられません。予測が間違っていたときに5×5のマスを掘ってしまうのが致命的です。epsが大きいときに予測のために掘る回数を増やしてみましたが、掘るコストが増えてしまうせいか、結果はよくなりませんでした。

悩みがつきません。

1000テストケースをまわしてみます。思ったよりもスコアがばらつくなあと思いました。100テストケースよりも結果が悪くなっています。

1000テストケース

5×5マスの予測を入れた後に3×3マスの中央を試し掘りしてみてあてはまる油田を調べることにしました。その後あてはまる油田がなかった調べて油田が合った場所をBFSし、さらにそれでも見つからなかったときは、全ての油田の場所からBFSをします。それでも見つからなかったら、epsが小さいときは掘っていない場所の中から油田のありそうなところを選んで掘り、それ以外はランダムで掘るようにしました。

100テストケースはやっと自己ベストを更新しました。

ドキドキしながら提出します。

結果は絶対スコアも相対スコアも悪くなりました。相対スコアは提出前の3,936,992,490から3,538,365,904に下がっています。順位も332位から423位に下がりました。

あれ?

でも今回はそこまで悪くないと思っているのですが。得点源になっている箇所が悪化しているのかもしれません。相対スコアの場合、トップと差がつくと自分のスコアがほぼ0になってしまうということは経験済みです。ここは注意深く考えたいと思います。

絶対スコア:7628662450

相対スコア:3,538,365,904 423位/997人中

事前に穴を掘っておくのを5×5マスの中央に変更したら、さらにスコアがよくなりました。これならさすがに提出した結果も良くなるのではないでしょうか。

100テストケースの結果

提出した結果です。

あれ?

絶対スコアは少し良くなりました。それでもベストは越えません。相対スコアは下がりました。

謎は深まるばかりです。

絶対スコア:7529662450    46856 

相対スコア:3,467,801,792

過去ベストより下がっていたもの

悪化しているのはMが少ないときのようです。Mが小さいときのを気をつけるのと、あとは今思いついた、1行ずつN行、1列ずつN列占いをして、結果をクロスさせて一番油田がありそうなところを調べるということをしてみたいと思います。

と思いましたが、まずは推測を5×5だけでなく、4×4、3×3、2×2まで試したいと思います。

相対スコア:573位/1003位中

あまりよくなりません。

ここで先ほどの謎が解けました。100テストケースの結果を貼っていたつもりが51テストケースまでの結果までしか貼っていませんでした。

ぬか喜びをしました。5×5で占いをしておき、占いの結果が8割以上油田なら掘ります。また、事前に5×5の中央を掘っておくようにしました。

久しぶりに提出をしますが、25個がTLEで得点が0。相対スコアもガクンと落ちてしまいました。

TLE25

相対スコア

今やっている方法はこんな感じです。

seed0のビジュアライザ

1000テストケースを試しましたが過去のベストを超えられませんでした。

うーん、難しい。疲れてきたので一旦休憩します。

もう一回過去のベストからやり直したいと思います。

19.1行ずつ、1列ずつ占いをする

2024年2月18日の朝です。明日が最終日になりますが月曜日。今日がコンテストに時間を費やせる最後の日です。それでもいつもと違って夜まで時間があるので、精神的には少し楽かもしれません。

昨日寝ながら考えたのですが、今日は1行ずつ、1列ずつ占いをして、結果をクロスして油田の場所を予測したいと思います。

余談ですが、昨夜はABC341に午後9時から参加していたのですが、B問題の意味が何回読んでもわからなくて、ACしたのは67分後。途中でC問題を解いていたのですが、それもバグがみつからず右往左往。B問題をACしたらC問題のバグも見つかり、なんとか3完できました。D問題も誤読していたので、やっぱり睡眠不足と疲れがたまっていたのかもしれません。今日もうまくいかないと感じたときは早めにお昼寝をしたいと思います。

1行ずつ、1列ずつ占いをした結果です。行の結果と列の結果を掛け算しました。seed0、seed2ともに右の正解と比べても悪くなさそうです。

seed0 左:1行1列占いの結果 右:正解の油田

seed2 左:1行1列占いの結果 右:正解の油田

結果の良い場所から掘り進めてみます。

ああ、そうだ、補正するのを忘れていました。全部を足すと油田マスの数になるように調整します。うん、よさそう。

ビジュアライザを見ていると、うまくいっていないseed19を見つけました。

seed19の予測(左)と正解(右)

最初の予測だとうまくいっていない箇所があるので、1マスずつ調べたあとに予測を更新したいと思います。そして調べていないマスの中で予測値が一番大きいものを調べていくことにします。油田だったらBFSをします。

書き終えたので提出します。2個TLEしました。相対スコアは3,354,956,697、1066人中461位でした。

AC48,TLE2

相対スコア:3,354,956,697 461位/1066人中

BFSから重ね合わせた差分が小さいものを調べるように変更します。

重ね合わせにしたものの、一部は良くなりましたが、一部は悪くなりました。

20.5日間ぶりに自己ベストを更新

油田の数が2個のときだけ重ね合わせをするようにして、それ以外はこれまでの過去のベストの二分探索法で行うようにします。

書き終えたので提出すると、2月13日に出したベストのスコアをやっとほんの少しだけですが更新することができました。絶対スコアは6798256874になり、相対スコアは提出前の480位から403位に上がりました。

絶対スコア:6798256874

相対スコア:3,579,373,021 400位/1084人中

seed0のビジュアライザ Score = 47745967

M=2のとき、合っているとわかった段階で埋めるのをやめても良いかもしれません。また最初の方針をもう一度使うことにしたので推測の更新をきちんと入れたいと思います。

M=2のとき、1個目が確定し、2個目は合っているとわかった段階でやめました。100テストケースの結果が少しよくなったので提出します。絶対スコアは少しだけ悪くなり、相対スコアは411位から408位に少しだけよくなりました。

絶対スコア:6802495757

相対スコア:3,404,510,669 408位/1089人中

1000テストケースをまわしたら、5個ほどUnexpected EOFが出ていて得点が0になっていました。見つからなかったときに今は何種類かの解法を加えていて、ランダムに掘って見つけた後に答えの出力をしていないものがあったので修正しましました。

21.終わりに

コンテスト最終日、2024年2月19日の朝です。今日は仕事なので、今回のコンテストはこれで終了です。現在の順位表の1位はeijirouさんです。

現在の順位表のトップ(2024年2月19日午前6時半現在)

相対スコア順位表:439位/1114人中

私の現在の順位は439位です。相対スコアがトップの十分の一もありません。難しかった。10日間のコンテストでしたが、あまり改善できなかったなあと思います。どの範囲を推定するかとか一致の判定とか、もっと良い方法がありそうに思います。推定の更新の方法もきちんと勉強しないとなあと思いました。油田は中心から調べ始めることが多かったので、油田の形の左上の位置を見つける良い方法を思いつくことができませんでした。重なっているというのが掘れば2以上の値だとわかるのですが、そこの部分が自分の中で難しく感じました。

それでも取り組み始めるとあっという間に時間が過ぎてしまうという、とても幸せな時間を過ごすことができました。ああでもない、こうでもないと考えている時間はとても楽しいものです。今回も入青はダメかもしれませんが次こそは良い結果を出せますように。

19時にコンテストが終わった後に多くの人が解法をXにポストしてくれることでしょう。他の人の解法を聞くのが楽しみです。そしてコンテストが終わったら、午後10時から感想会スペースを開く予定です。ぜひお気軽に参加してもらえればなあと思っています。

AWTFの対象になったことも関係しているのでしょうか。コンテストの参加者が増えているように思います。もっと増えるといいなあ。そしてまだ参加したことがないけど興味を持っていただけた方がいたら、次はぜひ一緒にコンテストに参加しましょう。一方、すでにコンテストに参加している方はぜひ次のコンテストでも競い合いましょう。

seed0のビジュアライザ Score = 29745967
22.最終提出するのを忘れていたので提出します

Mが24より大きいときの分割推測で5×5マスを全て埋めていたので16マス以上のときはやめることにしました。100テストケースの結果はそんなに変わらなかったので提出をします。するとTLEが2個でました。しかし相対スコアは3,505,185,130に上がりました。順位も提出前の445位から384位に上がりました。

TLE2個

相対スコア:3,505,185,130 384位/1115人中

全部でACを取るコードよりも、いくつかのテストケースで少しでも良いスコアが出ることの方が相対スコアを上げるのには必要なのかもしれません。ということで、WAが出たままですが、これを最終提出としたいと思います。

と思ったのですが、念のために1000テストケースをまわすと、大量のTLEが発生しました。空っぽの答えを提出していることがあるようです。修正して今度こそ最終提出をします。

23.最終結果(2024/3/1更新)

更新が遅くなりました。システムテストの結果はシステムテスト前の404位から399位に上がりました。3000テストケースは全てACしていました。

システムテストの結果:190,775,312,523 399位/1132人中

解説にリンクが貼ってある詳細順位表(AHC Standings)を見ると私の場合、Mが大きいときが得点源となっていたのですが、実はMが大きいときというのはテストケースの中でごくわずかでした。本当はMが小さいときのスコアが少しでも良くなるようにがんばらなければいけなかったのでした。

得点源はMが大きいときのみ

1000テストケースを分類

成績は振るわなかったものの、ヒューリスティックのレーティングが2上がったことで1600になりました。ついに青になりました!うれしい。

ヒューリスティックのレーティング:1600(青)
24.復習

その後、推定系の問題が苦手なので復習をしています。ベイズ推定と相互情報量の勉強をしているところです。本当は復習が終わったらブログを更新しようと思っていたのですが、思った以上に時間がかかっているので先に更新をすることにしました。

M=2ののとき限定で占うマスの集合を相互情報量/costが最大になるような山登りを書こうと思っているのですが、うまくいかずにいます。これができるとコストが1を切ることができます。

参考にしているのがAHCラジオとあぷりしあさんの記事です。他の方のブログを読んだり、ベイズ推定の本を読んだりもしています。うまくできたらまた更新したいと思います。

www.youtube.com

qiita.com

qiita.com

25.延長戦100位になりました

M=2のときのテストケースが50個中5個あります。そのうち4個ACしていて、1個はTLEしたままです。それでも相対スコアは倍になりました。

相対スコア:6,263,775,278 延長戦100位に(2024/3/7時点)

「占うマスの集合を相互情報量/costが最大になるような山登り」がM=2でも実行時間3秒におさめるのが難しくて、悩みました。あぷりしあさんの2番目の記事のコードも実行時間が制限時間には間に合わない様子。しかし、どこを改良すればわかりませんでした。

全部の候補を見ていると時間が足りないので、占うマスを最初はランダムに選び、1回0.3sで山登りを区切るといったことをしました。最初は乱択で占うマスを選んだベイズ推定から、相互情報量/costが最大になる占いマスの集合に移行していきます。占うマスを乱択で選ぶだけよりもさらにスコアが伸びました。

ベイズ推定も相互情報量もまだ理解できていないところがたくさんあるのですが、動くコードが書けてよかったなぁと思います。記事を書いてくれたあぷりしあさんには感謝しかありません。

それでは次の復習(第一回マスターズ選手権-予選-)へと進みたいと思います。

seed0のビジュアライザ Score = 566021