milkcoffeeのブログ

競技プログラミングなど

【AHC024】 19位解法

AtCoder Heuristic Contest 024 で 19位を取ることが出来ました。

順位表の1ページ目に載るのはアルゴ部門含めても初めてのことで嬉しいです。

記念に書いてみたかった解説記事を書こうと思います。

 

最終提出のビジュアライザは以下の通りです。

seed : 0 で 1935点です。

最終提出の内容

提出したコードのアルゴリズムは以下の通りです。

  1. 行・列を削除する。
  2. ランダムに隣接するマスの色に置き換える。
  3.  1と2 を反復する。
  4. 外側を空白にする。

以下に詳細や実装方法などを書きます。

1. 行・列を削除する。

位置関係を保ったまま大きい区画を縮めたくなり、この操作を思いつきました。

実装としては マスが存在する全ての列において以下を行ってます (行も同様)。

  1. 選んだ列を全て空白に置き換える。
  2. その列より右を全て 1 マスずつ左にずらす。
  3. その結果、条件を満たすならば採用。満たさないならば元に戻す。

削除は行と列で交互に行って「1行目、1列目、2行目、2列目・・・」みたいに見ています(これが良いかどうかは怪しい)。

また、条件を満たすかどうかの判定は高速化は特にせず、 O(N^2) で行っています。

 

seed:0 でこれを 1 周すると以下のようになります。これだけでも 1000 点超えます。

2. 隣接するマスの色に置き換える

行・列の削除をより行えるようにするためには、盤面に変化を加えたいです。

そのために隣接するマスの色に置き換えることを行います。

削除できる行・列が無くなるたびに、以下の操作を1000回行います。

  • ランダムに(空白でない)マスを選び、それと隣接するマスの色に置き換える。
    • 隣接する色も同じ色だった場合は置き換えずスルーする。
    • 隣接するマスが空白の場合、実行時間が 1 sec 未満ならばスルーする。
  • 置き換えた結果、条件を満たさなくなったら元に戻す。

seed:0 で実験したところ 1000 回がちょうど良かったので1000回にしています。

「隣接するマスが空白の場合、実行時間が 1 sec 未満ならばスルー」というのは、早い段階で空白マスへの置き換えを許容してしまうことで削除できた行ができなくなったりするため入れた処理です。

ここでの条件を満たすかの判定も高速化していません (ここは流石にした方が良かった)

隣接マスの色に置き換える処理を入れたことにより、削除できる行・列が増え、よりスコアが伸びました。

3. 1 と 2 を繰り返す。

時間いっぱい 1 と 2 を繰り返します。

高速化をしていないため、ここのループは20回ほどしか回っていません。

4. 外側を空白にする

外側の無駄な土地をできるだけ空白にします。

賢い方法が思いつかなかったので、以下の処理を2回行っています。

  • 空白マスと隣接するマスを空白マスに置き換える。条件を満たさなくなればもとに戻す。

 

これらを実装した結果が以下のビジュアライザになります。(最初に載せたものと同じ)

やらなかったこと

やったけど上手く行かずに不採用 or 思いついたけどやらなかった、やれなかったことのまとめです。

  • 地図を1から構築する (かなりしんどそうなので最初に捨てた)
  • 行・列だけでなく斜めにマスを選んで削除 (やってみたけど削除できる場合が少なすぎた)
  • 削除する行・列をランダムにして、複数の状態を保つビームサーチ (試行回数が少なすぎるため改善が見込めない、高速化が上手く出来ていれば効果あるかも)
  • 色iと色j の隣接個数の差分を計算することによる高速化 (時間がなく断念)
  • 行・列の全体ではなく部分を削除 (時間がなくて断念)

良かった点

  • 盤面を保持する二次元配列の外側に色0のマスを 1周分作ることで、実装がかなり楽になった。
  • 前回のAHCから class を使うようになり、実装がかなり楽になった。
  • 高速化を諦めてとりあえず点が出る方法を実装したため、時間内に間に合った。

反省点

  • seed:0 しか見ていなかったので多様なケースに対応出来なかった。
  • 終盤、新しい操作を考えるよりもパラメータ調整などに時間を使ってしまった。
  • 順位表を見てドキドキするだけの無駄な時間があった。

感想

問題を見た瞬間にこれは楽しそうだなと思って、実際に楽しみながら良い順位を取ることができたので良かったです。

考察については、行・列の削除という操作が早めに思いついてそこからスムーズに進んみました。上位の方と方針がわりと似ていて、あたり方針を引くことが出来きたなと思います。

実装についても、途中参加でかなり焦りながら実装していましたが、特にバグらせずに実装し続けることができ、自分にとってはかなり調子が良かったと思っています。

 

また、今回でついにアルゴのレート (highest:2104) をマラソンのレートが超えました。

橙になりたいけど橙パフォはまだ安定する気がしていないので、かなり遠そうだなと思っています。

AHC は楽しいのでこれからも頑張っていきます。現在就活生ですが、ヒューリスティックや最適化をやっている会社も良いなぁという気持ちになっています。

 

記事は以上になります。ありがとうございました。