競技プログラミング練習会2015 Normal 第2回
-
Upload
hideaki-nagamine -
Category
Engineering
-
view
481 -
download
0
Transcript of 競技プログラミング練習会2015 Normal 第2回
2015/04/17長嶺英朗(ID:hnagamin)
競技プログラミング練習会2015 Normal
第2回
目次
● スタックとキュー● 全探索
– 幅優先探索– 深さ優先探索
● 累積和
データ構造
● データ構造は多数のデータをある秩序に従って保存しておくための構造です– 例) 配列、ハッシュテーブル、木、スタック、キュー…
● データ構造には様々な種類があり、それぞれ得意なことと不得意なこと、可能なことと不可能なことがあります
● 今日はスタックとキューの話をします
スタック
● 「後入れ先出し」 (Last In, First Out)のデータ構造
● 次のことがO(1)でできる● push: 先頭に要素を追加する● pop: 先頭の要素を取り出す
● 本の山みたいなイメージ
push
pop
キュー
● 「先入れ先出し」 (First In, First Out)のデータ構造
● 次のことがO(1)でできる● enqueue: 先頭に要素を追加する● dequeue: 末尾の要素を取り出す
● 店の行列的なイメージ
enqueue
dequeue
スタックを使う問題の例http://poj.org/problem?id=2559
全探索
全探索
● いくつかの組合せの中からある特定のものを探すとき、考えるべき組合せが比較的少ない場合にはそれらを全て調べてしまうのが有効なことがある
● 「比較的少ない」: 106通りくらい
全探索が有効な例
● 3×3魔法陣の解の個数を求める
● 3x3マスに1~9の数字を入れて魔法陣か確かめる
● 考えるべき組合せは9!通り
● 9! = 362880 < 106
● 間に合う
2 9 47 5 36 1 8
全探索が有効な例
● 8クイーン問題の解のひとつを求める
● 8x8チェス盤に8つのクイーンを置く● どのクイーンも他の駒の利きにないよう置く
8クイーン問題の解の一例
http://ja.wikipedia.org/wiki/エイト・クイーン
全探索が有効な例
● 普通に並べると64C8 通り
– ちょっと大きい● 工夫が必要
全探索が有効な例
● 普通に並べると64C8 = 4426165368 通り
– ちょっと大きい● 工夫が必要
全探索が有効な例
● よく考えると、2つのクイーンは同じ列・同じ行には並ばない
● {1, 2, ... 8} の順列をクイーンの位置に対応させる
● 8! = 40320● 間に合う
(7, 5, 3, 1, 6, 8, 2, 4)
全探索
● 考えるべき状態を木として扱うことが多い
1 2 3 4 5
1 31 2 1 4 2 1
…
18 1914
深さ優先探索
● 葉に到達するまで子要素を探索してから次の子要素を探索する
1
2 11 15
3 5 8 12 13 16 17
4 6 7 9 10
深さ優先探索
● スタックを使って深さ優先探索が実現できる● まだ探索していない頂点をスタックに積んでから、
スタックから頂点を取り出して深さ優先探索する
18 1917
幅優先探索
● 子要素を全て探索してから子要素の子要素を探索する
● 根に近い順に探索していく
1
2 3 4
5 6 7 8 9 10 11
12 13 14 15 16
幅優先探索
● キューを使って幅優先探索が実現できる● 今見ている頂点の子要素を全てキューに突っ込ん
でから、キューから頂点を1つ取りだして幅優先探索する
深さ優先探索のココがすごい!
● メモリ消費量が幅優先に比べて少ない!● 再帰を使うことで楽に書ける!
– 再帰を使って書くときは、暗黙のうちにコールスタックを使っている
● 葉に至るまでが長い分枝が存在するとつらい!– 木の深さが有限でない場合終わらないことがある
幅優先探索のココがすごい!
● ある種の最小解が求まる!– 例えば、頂点として迷路内の座標を設定しゴールに向
かって幅優先探索すると迷路を出るための最短経路が求まる
● (解があれば)(木の深さが有限でなくても)
必ず見つける!● メモリを大量に使う!
累積和
要求
● 長さNの配列が与えられて、その中にはN個の数が格納されている
● q個のクエリ(問題)が与えられるので、それに答える
– 問題: 「i番目からj番目までの要素の和を答えよ」
● N 10≦ 6 , q 10≦ 6
愚直な解法
● 各クエリに対して、一つひとつ和を求めていく
愚直な解法
● 各クエリに対して、一つひとつ和を求めていく● O(qN)
– 各クエリの処理に最大O(N)回の計算が必要
– クエリはq個
● qN 10≦ 12
– ちょっと大変
累積和
● クエリを処理する前に予めSi = (0番目からi番目までの要素の和)を求めておく
● 各クエリに対してSj - Si-1を返せば良い
3 1 4 1 5 9 2 6 53 1 4 1 5 9 2 6 5
累積和
● クエリを処理する前に予めSi = (0番目からi番目までの要素の和)を求めておく
● 各クエリに対してSj - Si-1を返せば良い
3 1 4 1 5 9 2 6 5
3 4 8 9 14 23 25 31 36
計算量
● Siを求めるのにO(N)
– Si = Si-1 + ai を利用する
● 各クエリに対してO(1)● 従って、計算量はO(N + q)● 間に合う