Ce diaporama a bien été signalé.
Nous utilisons votre profil LinkedIn et vos données d’activité pour vous proposer des publicités personnalisées et pertinentes. Vous pouvez changer vos préférences de publicités à tout moment.

深さ優先探索による塗りつぶし

32 015 vues

Publié le

深さ優先探索による塗りつぶしの解説です

Publié dans : Formation
  • Soyez le premier à commenter

深さ優先探索による塗りつぶし

  1. 1. 深さ優先探索による 塗りつぶし 2015/6/6 1
  2. 2. 深さ優先探索とは 探索とは • 探索とは,可能性を調べながら,解を探す方法です 深さ優先探索とは • 最も基礎的な探索の方法です 本スライドで学ぶこと • 深さ優先探索による「塗りつぶし」 • 深さ優先探索の再帰関数による実装 • 深さ優先探索のスタックによる実装 2015/6/6 2
  3. 3. ©AtCoder Inc. All rights reserved. 3 問題 2015/6/6 3
  4. 4. 問題 s......... #########. #.......#. #..####.#. ##....#.#. #####.#.#. g.#.#.#.#. #.#.#.#.#. #.#.#.#.#. #.....#... 2015/6/6 4 入力 • 右図のような迷路 • . が通れる 出力 • s から g までいけるか?
  5. 5. 例 2015/6/6 5 s......... #########. #.......#. #..####.#. ##....#.#. #####.#.#. g.#.###.#. #.#.#.#.#. ###.#.#.#. #.....#... s......... #########. #.......#. #..####.#. ##....#.#. #####.#.#. g.#.#.#.#. #.#.#.#.#. #.#.#.#.#. #.....#... ↑行ける ↑行けない
  6. 6. ©AtCoder Inc. All rights reserved. 6 塗りつぶし Flood-fill 2015/6/6 6
  7. 7. 問題を解くアプローチ 問題の解き方 1. s から行ける場所を全部調べる 2. g に行けてれば “yes”,行けなかったら “no” 「s から行ける場所を全部調べる」 • これを塗りつぶし (flood-fill) と呼びます • とても良く使います 2015/6/6 7 これのイメージ
  8. 8. 塗りつぶしの例 2015/6/6 8 s......... #########. #.......#. #..####.#. ##....#.#. #####.#.#. g.#.###.#. #.#.#.#.#. ###.#.#.#. #.....#... s......... #########. #.......#. #..####.#. ##....#.#. #####.#.#. g.#.###.#. #.#.#.#.#. ###.#.#.#. #.....#... s から行ける領域 ↑
  9. 9. ©AtCoder Inc. All rights reserved. 9 深さ優先探索による 塗りつぶし 2015/6/6 9
  10. 10. 深さ優先探索による塗りつぶし 基本的な考え方 • 今居るところから隣に行こうとしてみる • まだ行ってなかったら行く ちゃんと塗りつぶすために • 全箇所から 4 方向への移動を試しつくす • そのために,試しつくしてない場所を覚えてお き,戻ってくる 2015/6/6 10
  11. 11. 深さ優先探索による塗りつぶし 基本:今いる所の隣を塗る 2015/6/6 11 ######.#.## ######.#.## #s......... ######.#### ######.#### 最初は s からスタート
  12. 12. 深さ優先探索による塗りつぶし 基本:今いる所の隣を塗る 2015/6/6 12 ######.#.## ######.#.## #s......... ######.#### ######.#### 右隣へ移動(赤の矢印は s からの経路)
  13. 13. 深さ優先探索による塗りつぶし 基本:今いる所の隣を塗る 2015/6/6 13 ######.#.## ######.#.## #s......... ######.#### ######.#### 右隣へ移動(赤の矢印は s からの経路)
  14. 14. 深さ優先探索による塗りつぶし 基本:今いる所の隣を塗る 2015/6/6 14 ######.#.## ######.#.## #s......... ######.#### ######.#### 右隣へ移動(赤の矢印は s からの経路)
  15. 15. 深さ優先探索による塗りつぶし 基本:今いる所の隣を塗る 2015/6/6 15 ######.#.## ######.#.## #s......... ######.#### ######.#### 分かれ道だけど,とりあえず気にせず進む
  16. 16. 深さ優先探索による塗りつぶし 基本:今いる所の隣を塗る 2015/6/6 16 ######.#.## ######.#.## #s......... ######.#### ######.#### 分かれ道だけど,とりあえず気にせず進む
  17. 17. 深さ優先探索による塗りつぶし 基本:今いる所の隣を塗る 2015/6/6 17 ######.#.## ######.#.## #s......... ######.#### ######.#### 分かれ道だけど,とりあえず気にせず進む
  18. 18. 深さ優先探索による塗りつぶし 基本:今いる所の隣を塗る 2015/6/6 18 ######.#.## ######.#.## #s......... ######.#### ######.#### 分かれ道だけど,とりあえず気にせず進む
  19. 19. 深さ優先探索による塗りつぶし 進めるところが無くなったら戻る 2015/6/6 19 ######.#.## ######.#.## #s......... ######.#### ######.#### もう進めるところがない!
  20. 20. 深さ優先探索による塗りつぶし 進めるところが無くなったら戻る 2015/6/6 20 ######.#.## ######.#.## #s......... ######.#### ######.#### なので戻ります
  21. 21. 深さ優先探索による塗りつぶし 進めるところが無くなったら戻る 2015/6/6 21 ######.#.## ######.#.## #s......... ######.#### ######.#### また戻ります
  22. 22. 深さ優先探索による塗りつぶし 戻ってきて別のところに行けたらそっちに行く 2015/6/6 22 ######.#.## ######.#.## #s......... ######.#### ######.#### ここはまだ上に行ってない!
  23. 23. 深さ優先探索による塗りつぶし 戻ってきて別のところに行けたらそっちに行く 2015/6/6 23 ######.#.## ######.#.## #s......... ######.#### ######.#### なので今度は上に行ってみます
  24. 24. 深さ優先探索による塗りつぶし 戻ってきて別のところに行けたらそっちに行く 2015/6/6 24 ######.#.## ######.#.## #s......... ######.#### ######.#### 一番上まで行ったらまた戻ります
  25. 25. 深さ優先探索による塗りつぶし 戻ってきて別のところに行けたらそっちに行く 2015/6/6 25 ######.#.## ######.#.## #s......... ######.#### ######.#### 一番上まで行ったらまた戻ります
  26. 26. 深さ優先探索による塗りつぶし 戻ってきて別のところに行けたらそっちに行く 2015/6/6 26 ######.#.## ######.#.## #s......... ######.#### ######.#### 一番上まで行ったらまた戻ります
  27. 27. 深さ優先探索による塗りつぶし 戻ってきて別のところに行けたらそっちに行く 2015/6/6 27 ######.#.## ######.#.## #s......... ######.#### ######.#### もう行く所がないのでさらに戻ります
  28. 28. 深さ優先探索による塗りつぶし 戻ってきて別のところに行けたらそっちに行く 2015/6/6 28 ######.#.## ######.#.## #s......... ######.#### ######.#### もう一個戻って
  29. 29. 深さ優先探索による塗りつぶし 戻ってきて別のところに行けたらそっちに行く 2015/6/6 29 ######.#.## ######.#.## #s......... ######.#### ######.#### 上と下も行って帰ってきて(省略)
  30. 30. 深さ優先探索による塗りつぶし 戻ってきて別のところに行けたらそっちに行く 2015/6/6 30 ######.#.## ######.#.## #s......... ######.#### ######.#### s まで戻ったら完了!
  31. 31. 余談:「深さ優先探索」? 何故これが深さ優先探索? まだ 4 方向を試し尽くしていない場所の中で,一 番「深い」場所から探索を広げるから • 試し尽くしていない場所 = 青 or 赤 • 深い = s から遠い • 一番「深い」場所 = 赤 今後紹介する「幅優先探索」等との 対比でよくわかると思います 2015/6/6 31 ######.#.## ######.#.## #s......... ######.#### ######.####
  32. 32. ©AtCoder Inc. All rights reserved. 32 再帰関数による 深さ優先探索 2015/6/6 32
  33. 33. 再帰関数による深さ優先探索 考え方 • 位置を引数にした再帰関数を使う • 自分から 4 方向への呼び出しを行う 何故これで深さ優先探索になる? • 再帰関数なので呼び出した後戻ってくる • 戻ってきて違う方向へまた呼び出す 2015/6/6 33
  34. 34. 擬似コードでの例 関数 search(x, y) { if (場所 (x, y) が壁か迷路の外) return if (既に (x, y) に一度到達している) return (x, y) に到達したということを記録 // 4 方向を試す search(x + 1, y) // 右 search(x - 1, y) // 左 search(x, y + 1) // 下 search(x, y – 1) // 上 } 2015/6/6 34 関数 search をスタートの 座標から呼び出す 再帰関数なので,1 つの方向を試し終わった 後,帰ってきて次の方向を試す → 全ての位置から 4 方向を試し尽くせる
  35. 35. 擬似コードでの例 関数 search(x, y) { if (場所 (x, y) が壁か迷路の外) return if (既に (x, y) に一度到達している) return (x, y) に到達したということを記録 // 4 方向を試す search(x + 1, y) // 右 search(x - 1, y) // 左 search(x, y + 1) // 下 search(x, y – 1) // 上 } 2015/6/6 35 ######.#.## ######.#.## #s......... ######.#### ######.#### • 色が付いている所 = 「到達した」と記録されている所 • 青 = 再帰関数で呼び出し中の(後で戻ってくる)場所 • 赤 = 再帰関数で今訪れている場所 • 紫 = 既に再帰関数から抜けた(もう戻ってこない)場所
  36. 36. C での例 int W, H; // 横幅と縦幅 char maze[MAX_W][MAX_H]; // 迷路 bool reached[MAX_W][MAX_H]; // 到達できる? void search(int x, int y) { // 迷路の外側か壁の場合は何もしない if (x < 0 || W <= x || y < 0 || H <= y || maze[x][y] == ‘#’) return; // 以前に到達していたら何もしない if (reached[x][y]) return; reached[x][y] = true; // 到達したよ // 4 方向を試す search(x + 1, y); // 右 search(x - 1, y); // 左 search(x, y + 1); // 下 search(x, y – 1); // 上 } 2015/6/6 36 関数 search をスタートの 座標から呼び出す
  37. 37. ©AtCoder Inc. All rights reserved. 37 スタックによる 深さ優先探索 2015/6/6 37
  38. 38. スタックによる深さ優先探索 考え方 • 試すべき位置をスタックで管理 • 再帰呼び出しの代わりに,スタックへ push アルゴリズム • 最初はスタート地点をスタックに投入 • 繰り返す:スタックから位置を取り出して,まだ訪れて いない隣があれば push 今回は詳細な解説は省略します. 今後アップロード予定の幅優先探索の解説にて,深さ優先探索のこの 方針での実装についても言及します. 2015/6/6 38
  39. 39. スタックによる深さ優先探索 • 再帰関数が深くなりすぎると「スタックオーバーフ ロー」が起こって実行時エラーになることがあります. • スタックを用いたこっちの実装法ならば回避できます. 2015/6/6 39
  40. 40. ©AtCoder Inc. All rights reserved. 40 おわりに 2015/6/6 40
  41. 41. 塗りつぶし 塗りつぶしの他の出番 • 行ける領域の大きさを計算する • 連結なグループの個数を数える • などなど…… その他の塗りつぶしアルゴリズム • 今回は深さ優先探索による方法を紹介 • 塗りつぶしを行う方法は多数存在 詳しくは以下を参照 http://en.wikipedia.org/wiki/Flood_fill 2015/6/6 41 s......... #########. #.......#. #..####.#. ##....#.#. #####.#.#. g.#.###.#. #.#.#.#.#. ###.#.#.#. #.....#...
  42. 42. 深さ優先探索 深さ優先探索の他の出番 • 組合せを全て試す全探索 • その高速化である枝刈り探索 深さ以外を優先する探索 • 幅優先探索 • 最良優先探索 (→ Dijkstra / Prim のアルゴリズム) 塗りつぶしは幅優先探索などでやっても正しく行える. 深さ優先探索を使う利点は,再帰関数で簡単に書けること. 2015/6/6 42

×