Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

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

21,195 views

Published on

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

Published in: Education
  • Be the first to comment

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

  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

×