概要
問題文 → ■, ■
公式解説 → なさそう?
自分の提出 → ■ など
JOI の output only の問題です。
Heuristic contest タイプの問題で、厳密解が得られなくともそこそこ良い解を出力することが要求されています。また、手元実行でよいため実行時間制限はあまり気にしないでよく、例えば数十分の実行時間を前提とすることもできます。
出力に対する評価方法は、当時参加者による相対評価です。全ケースで、当時参加者ベスト水準である
解法
クラスタリング
「
このクラスタリングという問題についての定跡のひとつに、K平均法 というアルゴリズムがあります。「解の良さ」を、各クラスタ中心点との平均
私は Python の、sklearn.cluster.KMeans を使いましたが、K平均法はアルゴリズムがかなり簡単なので、フルスクラッチで書いてもすぐに実装できるはずです。
初期解
K平均法により町をクラスタリングして、それぞれのクラスタに対して最小包含円を求めます。最小包含円の中心の座標は一般に整数とは限らないので、前後の格子点を試します。これで、解の候補が作れました。
ところで、K平均法は、あるランダム「初期状態」からの反復によりクラスタリングを行います。ランダム要素があるということは、この方法を反復試行して当たり待ちをするだけで、もっと良い解が手に入る可能性があります。
なんと、この方法で、
山登り法
惜しいことに、ひとつだけ
- あるクラスタに対する円にちょうど乗っている町を、ランダムに選ぶ。
- それの属するクラスタを、ランダムに変更してみる。
「
上述の K 平均法で作った初期解から、この山登り法を適用することで、全ケースで
さらに調整
今回の近傍のとり方では山登りをしても大きく結果が改善することはなく、どちらかというと「初期解」の質にかなり左右するように思われました。そこである程度多くの「初期解」を作り、最優秀付近の「初期解」に対してのみ山登り法を試みることで、さらにスコアが上がりました。
結果
ひとつあたり実行時間が数分という感じで調整。
- [building1] 207849677458(■)
- [building2] 233441687031(■)
- [building3] 166415929095(■)
- [building4] 126901378706(■)
- [building5] 242636173758(■)