Se ha denunciado esta presentación.
Utilizamos tu perfil de LinkedIn y tus datos de actividad para personalizar los anuncios y mostrarte publicidad más relevante. Puedes cambiar tus preferencias de publicidad en cualquier momento.

Chokudai Contest 001

2.848 visualizaciones

Publicado el

Chokudai Contest 001 解説

Publicado en: Educación
  • Sé el primero en comentar

Chokudai Contest 001

  1. 1. ©AtCoder Inc. All rights reserved. 1 Chokudai Contest 001 解説 AtCoder株式会社 代表取締役 高橋 直大
  2. 2. ©AtCoder Inc. All rights reserved. 2 はじめに • Writer(chokudai)が、約8時間のテストプレイで試せ た方針のみ明記しています。 • もっと良い方針(89万点以上)は、Twitterのハッシュ タグ#chokudai_1から見つけることが可能かもしれま せん。そちらも併せてご確認ください。
  3. 3. ©AtCoder Inc. All rights reserved. 3 問題概要 • N×Nのマスに、1~100の整数が書かれている。 • マスをなぞると、マスの中に書かれている整数が1 減る – なぞる順は、中の整数が8,7,6,5…のように、1ずつ減って いるようにしなければならない – なぞれるマスは、今見ているマスの上下左右のみ • なぞる回数を出来るだけ小さくしなさい • 今回の問題ではN = 30
  4. 4. ©AtCoder Inc. All rights reserved. 4 まずは点数を取ろう! • 点数を取るには? – 連鎖とか考えずにとりあえず0にすることだけ考えよう! – 各マスについて、マスに書かれている整数分だけ座標を 出力する。 • これで、1~100で30*30マスあるとして、最大90000手 • 10万-手数がスコアなので、これで最低でも1ケース1万点 • 実際は平均50程度なので、45000手程度となり、5.5万点 – 10ケースあるのでおおよそ55万点が得られる。 2016/3/20 4
  5. 5. ©AtCoder Inc. All rights reserved. 5 ちょっと工夫をしよう! • 例えば、横に1個だけ繋げてみる – 右の数が自分より1だけ小さかったら、そっちも減らす • これだけでもスコアが結構あがる! – それが出来たら、再帰処理をして、連続して減らす • これだけでも物凄く上がる! – これをちゃんと組むだけでも70万点くらい行きます。 • ちゃんと書いてないから自信ない 2016/3/20 5
  6. 6. ©AtCoder Inc. All rights reserved. 6 その他の工夫 • スコアを減らすマスを選んでみよう! – 大きい数から減らしていった方が良さそう? • 例えば、こんな貪欲法がある – 盤面の中から一番大きい整数を選ぶ。 – そこから上下左右を見て、繋げるところがあれば出来るだけ連鎖を させることを繰り返す。 – これも80万点弱取れる。 – たくさん減らせるマスを採用するべき? • こんな貪欲法もある – とりあえず全部のマスから出来るだけ繋げてみる – 一番長いものを採用する – これを最後まで繰り返す。 – これも80万点弱くらい? 2016/3/20 6
  7. 7. ©AtCoder Inc. All rights reserved. 7 ランダムを使おう! • ここから、ランダムで色々変えてみる – 色々試すと当然スコアも変わる! • 選択するマスを変えてみる • ルートを変えてみる – 制限時間いっぱいまで試して、一番良いスコアを選ぶ – これでもスコアは上がるが、そんなに上がらない • もうちょっと賢い方法を考えよう! 2016/3/20 7
  8. 8. ©AtCoder Inc. All rights reserved. 8 ランダムを使おう! • ビームサーチや焼きなまし – ビームサーチ • 途中までの手番のうち、K番目に良いものを保持する – 「良いもの」というのは、自分で適当な評価関数を作る » 減らせてる数とか » 各マスの減らされ具合の分布とか » 隣り合う数の近さとか » 孤立してるかとか » もちろん全部入れる必要はない • そのまま最後まで進めると、「ある程度良いものの候補」を保持して探索が出来る ので、単純なランダムより良い • 焼きなまし – 前の解をちょっと変えて試す! – 今回は使い辛そう? • この辺を頑張ると多分85万くらいまでは行きます。 – ここから先は、もうちょっと問題の性質を掴まないと難しい>< • 評価とか凄い頑張ると88万点台も出るっぽい・・・? 2016/3/20 8
  9. 9. ©AtCoder Inc. All rights reserved. 9 補足 • ビームサーチや焼きなましにも限界が! – 例えば、「54万点の出力の一部をランダムシャッフルした 後、シミュレートした答えを評価として焼きなましを行う」 • こんなんはまともなスコアが出ません – ビームサーチや焼きなましを覚えることより、ちゃんと問 題の性質を掴むことの方が大切! – 今回はこの辺りを使わなくても89万点は行けます。 2016/3/20 9
  10. 10. ©AtCoder Inc. All rights reserved. 10 減らし方についての考察 • 一度消した列をひたすら減らし続けたりしそう。 – 例えば右図矢印のようにすると・・・? • 赤い部分が孤立する! • 孤立すると連鎖できなくなる! – 逆に、横一線に減らすようにしてしまうと? • 孤立点はなくなる • 実は結構良い? – でも適当なのでやっぱり大したことない • どちらにしても「減らすパス」を意識しよう! 2016/3/20 10
  11. 11. ©AtCoder Inc. All rights reserved. 11 「パス」を先に決める考え方 • 先に、「どういう順番で減らすか」を決めてしまうとど うなるか? – 例えば横一列が{7, 3, 6, 5, 3, 4, 1}だったとする。 – この1列を消すのに何手掛かるか? • これは実は結構簡単に求まってしまう! 2016/3/20 11
  12. 12. ©AtCoder Inc. All rights reserved. 12 「パス」を先に決める考え方 • 横一列が{7, 3, 6, 5, 3, 4, 1}だったとする。 – とりあえず下図みたいに書ける – ここから、どう減らすのが最善かを考える 2016/3/20 12 1 2 3 4 5 6 7 1 2 3 1 2 3 4 5 6 1 2 3 4 5 1 2 3 1 2 3 4 1
  13. 13. ©AtCoder Inc. All rights reserved. 13 「パス」を先に決める考え方 • まず、赤く塗った部分は、前から繋がる部分が存在 しないので、絶対に塗らないといけない • ここから右下に伸ばすと、全てを埋め尽くせる – つまり、赤い部分を数えるだけで、手数が解る! 2016/3/20 13 1 2 3 4 5 6 7 1 2 3 1 2 3 4 5 6 1 2 3 4 5 1 2 3 1 2 3 4 1
  14. 14. ©AtCoder Inc. All rights reserved. 14 パスに対する手数の求め方 • 赤い部分の数え方は非常に簡単 – 各マスについて、max(0, 1つ前のマスとの差+1)が、赤い 部分の個数になる。 • 前のマスより1つ下がったところが最高到達点となるため。 – これを利用すると、マスの順序をパスと呼び、その個数を Lとすると、 • ライン全体の手数を求めるのは、ラインに含まれるすべてのマス の赤い部分を調べれば良いので、O(L) • ラインに1つマスを追加するのは、新規追加マスの赤い部分を調 べれば良いので、O(1) • ライン2つの結合も、結合部分だけ調べれば良いのでO(1) – 非常に早く計算出来る! 2016/3/20 14
  15. 15. ©AtCoder Inc. All rights reserved. 15 貪欲法との違い • 例えば、{8,7,6,5,4,4,3,2,1}みたいなのがあるとする – 貪欲法だと、大体こんな感じになる • 8,7,6,5,4を減らす • 7,6,5,4,3を減らす • 6,5,4,3,2を減らす • ・・・・ • {4,3,2,1,0,4,3,2,1}になり、ここから、2つの4,3,2,1を減らす – 12手? – 今回の方法だと、もっと賢くなる • 4,3,2,1を減らす • {8,7,6,5,4,3,2,1, 0}になり、これを減らす – 9手? – 貪欲法で生じていた無駄が、パスを決めることでなくなった! 2016/3/20 15
  16. 16. ©AtCoder Inc. All rights reserved. 16 全体をラインで埋めよう! • パスを作ることで効率よく処理できる? – なら全体を1本のパスで埋めちゃおう! • とりあえず雑にするとこんなん – これで1本道になった! – 実はこれでさっきの処理をすると84万点 • あとはこれを頑張って効率化しよう! – 線の引き方を工夫してロスをなくしたり – ランダムで色々ためしてみたり 2016/3/20 16
  17. 17. ©AtCoder Inc. All rights reserved. 17 全体をパスで埋めないとだめ? • さっきの例では全ての線を埋めたが、別に複数のパ スがあっても問題ない – 繋がっていない分ロスは生まれやすいが • よって、実装が大変だったらこれでも良い – これでも84万点近くに行きます。 2016/3/20 17
  18. 18. ©AtCoder Inc. All rights reserved. 18 パスの作り方 • 隣り合う数の差が小さくなるようにパスを作ることで、 手数を減らすことが出来る – つまり、パスの作り方で貪欲法を使う? • これをすると、無駄な隙間が出来てしまい、あまり良 いスコアにならない – 隙間が出来ないようにパスを作ろう 2016/3/20 18
  19. 19. ©AtCoder Inc. All rights reserved. 19 パスの作り方 探索編 • 例えばこの状態の時、 – たくさん埋まっているマスの評価を上げる • 3方向から埋められているマスは超評価を上げる(赤) • 2方向から埋められているマスは評価を上げる(緑) • 1方向から埋められているマスは普通の評価(青) – 行き止まりに気を付ければ、良いパスが作りやすい! • もうちょっと細かいところを気にした方がもちろん良い – これを評価に加えて探索する – 普通にやったら82万点くらい? • まともなパスにするのはだいぶ難しい – 凄く頑張ると88万点台? • ビームサーチとかが使えます。 2016/3/20 19
  20. 20. ©AtCoder Inc. All rights reserved. 20 パスの作り方 DP • 探索は難しい!DPにしよう! – dp[L][R][U][D][A][B]を使って状態を更新する • 長方形(L, U)-(R, D)の区間が最大で、四隅に0,1,2,3と番号をつけ た時に、パスの始点がA、終点がBな時の、最短手数を入れる » 最短と言っても、あくまで「見つけた中での最短」 – 横に分割する時は、dp[L][X][U][D][A][i]と、 dp[X][R][U][D][j][B]を使って更新する。縦もやる。 • イメージはこんな感じ。切るx座標Xや、接続点iが複数ある。 2016/3/20 20
  21. 21. ©AtCoder Inc. All rights reserved. 21 パスの作り方 DP • このDPも更新の仕方を複数作れる – 例えばこんな感じの分け方をすると、パスが2つ出来るが、 パスの始点・終点は維持される。 • もう一方は無視をするような形になる。 – こういう工夫を頑張って色々すると89万点に乗ります。 2016/3/20 21
  22. 22. ©AtCoder Inc. All rights reserved. 22 パスの作り方 DP • このDPも更新の仕方を複数作れる – 例えばこんな感じの分け方をすると、パスが2つ出来るが、 パスの始点・終点は維持される。 • もう一方は無視をするような形になる。 – こういう工夫を頑張って色々すると89万点に乗ります。 2016/3/20 22
  23. 23. ©AtCoder Inc. All rights reserved. 23 パスよりももっと工夫しよう! • 実はこの問題、「なぞる方向を右か下だけに限定す る」という制約をつければ、最適解が求まる! – 入口と出口で二部グラフを作り、最大マッチング • これだけで88.5万点出たりします。 2016/3/20 23 (1,1) 2 (2,1) 1 (1,2) 2 (2,2) 1 (1,1) 2 (1,1) 1 (2,1) 1 (1,2) 2 (1,2) 1 (2,2) 1 (1,1) 2 (1,1) 1 (2,1) 1 (1,2) 2 (1,2) 1 (2,2) 1
  24. 24. ©AtCoder Inc. All rights reserved. 24 DAGの最適解が出ることを利用すると? • なんでこれで解けるの? – (1,1)の時点で10だったとして、(4,3)の時点では? • 右に3回、下に2回移動しているので、絶対に5まで下がっている • これは、移動方法に依存しない – つまり、(A,B)時点でCの時、というパターンは、C-(A+B)が等しい パターンしか通らない! • 右下にしか行かない、という制約があるため – よって、200枚程度のレイヤーに分かれた感じになるため、上レ イヤーから順番に処理すれば、順番が前後するなどの事故が 起こらない。 • 中心位置を変えるなどをランダムで試したりすると89万 点弱まで出る! – 今のところパス解法の方が強いですが、こっちも強くなるかも 2016/3/20 24

×