Submit Search
Upload
動的計画法入門(An introduction to Dynamic Programming)
•
13 likes
•
9,501 views
K
kakira9618
Follow
1/8(水)千葉大学CCS勉強会 『動的計画法入門』の資料です。
Read less
Read more
Technology
Report
Share
Report
Share
1 of 55
Download now
Download to read offline
Recommended
AtCoder Regular Contest 030 解説
AtCoder Regular Contest 030 解説
AtCoder Inc.
指数時間アルゴリズム入門
指数時間アルゴリズム入門
Yoichi Iwata
双対性
双対性
Yoichi Iwata
Convex Hull Trick
Convex Hull Trick
HCPC: 北海道大学競技プログラミングサークル
色々なダイクストラ高速化
色々なダイクストラ高速化
yosupo
動的計画法
動的計画法
京大 マイコンクラブ
動的計画法を極める!
動的計画法を極める!
HCPC: 北海道大学競技プログラミングサークル
AtCoder Regular Contest 019 解説
AtCoder Regular Contest 019 解説
AtCoder Inc.
Recommended
AtCoder Regular Contest 030 解説
AtCoder Regular Contest 030 解説
AtCoder Inc.
指数時間アルゴリズム入門
指数時間アルゴリズム入門
Yoichi Iwata
双対性
双対性
Yoichi Iwata
Convex Hull Trick
Convex Hull Trick
HCPC: 北海道大学競技プログラミングサークル
色々なダイクストラ高速化
色々なダイクストラ高速化
yosupo
動的計画法
動的計画法
京大 マイコンクラブ
動的計画法を極める!
動的計画法を極める!
HCPC: 北海道大学競技プログラミングサークル
AtCoder Regular Contest 019 解説
AtCoder Regular Contest 019 解説
AtCoder Inc.
最小カットを使って「燃やす埋める問題」を解く
最小カットを使って「燃やす埋める問題」を解く
shindannin
Rolling hash
Rolling hash
HCPC: 北海道大学競技プログラミングサークル
Indeedなう B日程 解説
Indeedなう B日程 解説
AtCoder Inc.
AtCoder Regular Contest 042 解説
AtCoder Regular Contest 042 解説
AtCoder Inc.
楕円曲線と暗号
楕円曲線と暗号
MITSUNARI Shigeo
様々な全域木問題
様々な全域木問題
tmaehara
Re永続データ構造が分からない人のためのスライド
Re永続データ構造が分からない人のためのスライド
Masaki Hara
文法圧縮入門:超高速テキスト処理のためのデータ圧縮(NLP2014チュートリアル)
文法圧縮入門:超高速テキスト処理のためのデータ圧縮(NLP2014チュートリアル)
Shirou Maruyama
AtCoder Regular Contest 049 解説
AtCoder Regular Contest 049 解説
AtCoder Inc.
Binary indexed tree
Binary indexed tree
HCPC: 北海道大学競技プログラミングサークル
AtCoder Regular Contest 029 解説
AtCoder Regular Contest 029 解説
AtCoder Inc.
明日使えないすごいビット演算
明日使えないすごいビット演算
京大 マイコンクラブ
abc031
abc031
AtCoder Inc.
動的計画法
動的計画法
HCPC: 北海道大学競技プログラミングサークル
AtCoder Regular Contest 046
AtCoder Regular Contest 046
AtCoder Inc.
AtCoder Beginner Contest 029 解説
AtCoder Beginner Contest 029 解説
AtCoder Inc.
AtCoder Beginner Contest 023 解説
AtCoder Beginner Contest 023 解説
AtCoder Inc.
ACPC 2018 Day3 G: 回文部分列 (Palindromic Subsequences)
ACPC 2018 Day3 G: 回文部分列 (Palindromic Subsequences)
HCPC: 北海道大学競技プログラミングサークル
Spaceships 解説
Spaceships 解説
Masaki Hara
ウェーブレット木の世界
ウェーブレット木の世界
Preferred Networks
C#でこなすexcel課題
C#でこなすexcel課題
tosaka 2
C言語ポインタ講座 (Lecture of Pointer in C)
C言語ポインタ講座 (Lecture of Pointer in C)
kakira9618
More Related Content
What's hot
最小カットを使って「燃やす埋める問題」を解く
最小カットを使って「燃やす埋める問題」を解く
shindannin
Rolling hash
Rolling hash
HCPC: 北海道大学競技プログラミングサークル
Indeedなう B日程 解説
Indeedなう B日程 解説
AtCoder Inc.
AtCoder Regular Contest 042 解説
AtCoder Regular Contest 042 解説
AtCoder Inc.
楕円曲線と暗号
楕円曲線と暗号
MITSUNARI Shigeo
様々な全域木問題
様々な全域木問題
tmaehara
Re永続データ構造が分からない人のためのスライド
Re永続データ構造が分からない人のためのスライド
Masaki Hara
文法圧縮入門:超高速テキスト処理のためのデータ圧縮(NLP2014チュートリアル)
文法圧縮入門:超高速テキスト処理のためのデータ圧縮(NLP2014チュートリアル)
Shirou Maruyama
AtCoder Regular Contest 049 解説
AtCoder Regular Contest 049 解説
AtCoder Inc.
Binary indexed tree
Binary indexed tree
HCPC: 北海道大学競技プログラミングサークル
AtCoder Regular Contest 029 解説
AtCoder Regular Contest 029 解説
AtCoder Inc.
明日使えないすごいビット演算
明日使えないすごいビット演算
京大 マイコンクラブ
abc031
abc031
AtCoder Inc.
動的計画法
動的計画法
HCPC: 北海道大学競技プログラミングサークル
AtCoder Regular Contest 046
AtCoder Regular Contest 046
AtCoder Inc.
AtCoder Beginner Contest 029 解説
AtCoder Beginner Contest 029 解説
AtCoder Inc.
AtCoder Beginner Contest 023 解説
AtCoder Beginner Contest 023 解説
AtCoder Inc.
ACPC 2018 Day3 G: 回文部分列 (Palindromic Subsequences)
ACPC 2018 Day3 G: 回文部分列 (Palindromic Subsequences)
HCPC: 北海道大学競技プログラミングサークル
Spaceships 解説
Spaceships 解説
Masaki Hara
ウェーブレット木の世界
ウェーブレット木の世界
Preferred Networks
What's hot
(20)
最小カットを使って「燃やす埋める問題」を解く
最小カットを使って「燃やす埋める問題」を解く
Rolling hash
Rolling hash
Indeedなう B日程 解説
Indeedなう B日程 解説
AtCoder Regular Contest 042 解説
AtCoder Regular Contest 042 解説
楕円曲線と暗号
楕円曲線と暗号
様々な全域木問題
様々な全域木問題
Re永続データ構造が分からない人のためのスライド
Re永続データ構造が分からない人のためのスライド
文法圧縮入門:超高速テキスト処理のためのデータ圧縮(NLP2014チュートリアル)
文法圧縮入門:超高速テキスト処理のためのデータ圧縮(NLP2014チュートリアル)
AtCoder Regular Contest 049 解説
AtCoder Regular Contest 049 解説
Binary indexed tree
Binary indexed tree
AtCoder Regular Contest 029 解説
AtCoder Regular Contest 029 解説
明日使えないすごいビット演算
明日使えないすごいビット演算
abc031
abc031
動的計画法
動的計画法
AtCoder Regular Contest 046
AtCoder Regular Contest 046
AtCoder Beginner Contest 029 解説
AtCoder Beginner Contest 029 解説
AtCoder Beginner Contest 023 解説
AtCoder Beginner Contest 023 解説
ACPC 2018 Day3 G: 回文部分列 (Palindromic Subsequences)
ACPC 2018 Day3 G: 回文部分列 (Palindromic Subsequences)
Spaceships 解説
Spaceships 解説
ウェーブレット木の世界
ウェーブレット木の世界
Viewers also liked
C#でこなすexcel課題
C#でこなすexcel課題
tosaka 2
C言語ポインタ講座 (Lecture of Pointer in C)
C言語ポインタ講座 (Lecture of Pointer in C)
kakira9618
最短経路問題 & 最小全域木
最短経路問題 & 最小全域木
HCPC: 北海道大学競技プログラミングサークル
08. artisocレシピブック ダイクストラ法を高速化しよう
08. artisocレシピブック ダイクストラ法を高速化しよう
Masaki Tamada
Union find(素集合データ構造)
Union find(素集合データ構造)
AtCoder Inc.
アルゴリズムイントロダクション15章 動的計画法
アルゴリズムイントロダクション15章 動的計画法
nitoyon
Viewers also liked
(6)
C#でこなすexcel課題
C#でこなすexcel課題
C言語ポインタ講座 (Lecture of Pointer in C)
C言語ポインタ講座 (Lecture of Pointer in C)
最短経路問題 & 最小全域木
最短経路問題 & 最小全域木
08. artisocレシピブック ダイクストラ法を高速化しよう
08. artisocレシピブック ダイクストラ法を高速化しよう
Union find(素集合データ構造)
Union find(素集合データ構造)
アルゴリズムイントロダクション15章 動的計画法
アルゴリズムイントロダクション15章 動的計画法
Similar to 動的計画法入門(An introduction to Dynamic Programming)
C07
C07
anonymousouj
Algorithm 速いアルゴリズムを書くための基礎
Algorithm 速いアルゴリズムを書くための基礎
Kenji Otsuka
距離まとめられませんでした
距離まとめられませんでした
Haruka Ozaki
汎化性能測定
汎化性能測定
Masanori Yamada
20190625 OpenACC 講習会 第3部
20190625 OpenACC 講習会 第3部
NVIDIA Japan
TopCoder SRM614 解説
TopCoder SRM614 解説
EmKjp
OpenGLと行列
OpenGLと行列
miyosuda
OpenGLと行列
OpenGLと行列
miyosuda
Sec15 dynamic programming
Sec15 dynamic programming
Keisuke OTAKI
Monadicプログラミング マニアックス
Monadicプログラミング マニアックス
Tomoharu ASAMI
Let's Simulate a Quantum Computer with Pretty Scala
Let's Simulate a Quantum Computer with Pretty Scala
Takatomo Torigoe
シェーダー伝道師 第二回
シェーダー伝道師 第二回
hixi365
動的計画法の並列化
動的計画法の並列化
Proktmr
Trip
Trip
oupc
AtCoder Beginner Contest 020 解説
AtCoder Beginner Contest 020 解説
AtCoder Inc.
SGD+α: 確率的勾配降下法の現在と未来
SGD+α: 確率的勾配降下法の現在と未来
Hidekazu Oiwa
diffの真髄
diffの真髄
fuku68
Rでマンデルブロ集合
Rでマンデルブロ集合
Yoshiteru Kamiyama
パターン認識第9章 学習ベクトル量子化
パターン認識第9章 学習ベクトル量子化
Miyoshi Yuya
PBL1-v1-006j.pptx
PBL1-v1-006j.pptx
NAIST
Similar to 動的計画法入門(An introduction to Dynamic Programming)
(20)
C07
C07
Algorithm 速いアルゴリズムを書くための基礎
Algorithm 速いアルゴリズムを書くための基礎
距離まとめられませんでした
距離まとめられませんでした
汎化性能測定
汎化性能測定
20190625 OpenACC 講習会 第3部
20190625 OpenACC 講習会 第3部
TopCoder SRM614 解説
TopCoder SRM614 解説
OpenGLと行列
OpenGLと行列
OpenGLと行列
OpenGLと行列
Sec15 dynamic programming
Sec15 dynamic programming
Monadicプログラミング マニアックス
Monadicプログラミング マニアックス
Let's Simulate a Quantum Computer with Pretty Scala
Let's Simulate a Quantum Computer with Pretty Scala
シェーダー伝道師 第二回
シェーダー伝道師 第二回
動的計画法の並列化
動的計画法の並列化
Trip
Trip
AtCoder Beginner Contest 020 解説
AtCoder Beginner Contest 020 解説
SGD+α: 確率的勾配降下法の現在と未来
SGD+α: 確率的勾配降下法の現在と未来
diffの真髄
diffの真髄
Rでマンデルブロ集合
Rでマンデルブロ集合
パターン認識第9章 学習ベクトル量子化
パターン認識第9章 学習ベクトル量子化
PBL1-v1-006j.pptx
PBL1-v1-006j.pptx
Recently uploaded
TSAL operation mechanism and circuit diagram.pdf
TSAL operation mechanism and circuit diagram.pdf
taisei2219
Open Source UN-Conference 2024 Kawagoe - 独自OS「DaisyOS GB」の紹介
Open Source UN-Conference 2024 Kawagoe - 独自OS「DaisyOS GB」の紹介
Yuma Ohgami
[DevOpsDays Tokyo 2024] 〜デジタルとアナログのはざまに〜 スマートビルディング爆速開発を支える 自動化テスト戦略
[DevOpsDays Tokyo 2024] 〜デジタルとアナログのはざまに〜 スマートビルディング爆速開発を支える 自動化テスト戦略
Ryo Sasaki
【早稲田AI研究会 講義資料】3DスキャンとTextTo3Dのツールを知ろう!(Vol.1)
【早稲田AI研究会 講義資料】3DスキャンとTextTo3Dのツールを知ろう!(Vol.1)
Hiroki Ichikura
Postman LT Fukuoka_Quick Prototype_By Daniel
Postman LT Fukuoka_Quick Prototype_By Daniel
danielhu54
SOPを理解する 2024/04/19 の勉強会で発表されたものです
SOPを理解する 2024/04/19 の勉強会で発表されたものです
iPride Co., Ltd.
論文紹介:Automated Classification of Model Errors on ImageNet
論文紹介:Automated Classification of Model Errors on ImageNet
Toru Tamaki
スマートフォンを用いた新生児あやし動作の教示システム
スマートフォンを用いた新生児あやし動作の教示システム
sugiuralab
論文紹介:Content-Aware Token Sharing for Efficient Semantic Segmentation With Vis...
論文紹介:Content-Aware Token Sharing for Efficient Semantic Segmentation With Vis...
Toru Tamaki
論文紹介:Semantic segmentation using Vision Transformers: A survey
論文紹介:Semantic segmentation using Vision Transformers: A survey
Toru Tamaki
Recently uploaded
(10)
TSAL operation mechanism and circuit diagram.pdf
TSAL operation mechanism and circuit diagram.pdf
Open Source UN-Conference 2024 Kawagoe - 独自OS「DaisyOS GB」の紹介
Open Source UN-Conference 2024 Kawagoe - 独自OS「DaisyOS GB」の紹介
[DevOpsDays Tokyo 2024] 〜デジタルとアナログのはざまに〜 スマートビルディング爆速開発を支える 自動化テスト戦略
[DevOpsDays Tokyo 2024] 〜デジタルとアナログのはざまに〜 スマートビルディング爆速開発を支える 自動化テスト戦略
【早稲田AI研究会 講義資料】3DスキャンとTextTo3Dのツールを知ろう!(Vol.1)
【早稲田AI研究会 講義資料】3DスキャンとTextTo3Dのツールを知ろう!(Vol.1)
Postman LT Fukuoka_Quick Prototype_By Daniel
Postman LT Fukuoka_Quick Prototype_By Daniel
SOPを理解する 2024/04/19 の勉強会で発表されたものです
SOPを理解する 2024/04/19 の勉強会で発表されたものです
論文紹介:Automated Classification of Model Errors on ImageNet
論文紹介:Automated Classification of Model Errors on ImageNet
スマートフォンを用いた新生児あやし動作の教示システム
スマートフォンを用いた新生児あやし動作の教示システム
論文紹介:Content-Aware Token Sharing for Efficient Semantic Segmentation With Vis...
論文紹介:Content-Aware Token Sharing for Efficient Semantic Segmentation With Vis...
論文紹介:Semantic segmentation using Vision Transformers: A survey
論文紹介:Semantic segmentation using Vision Transformers: A survey
動的計画法入門(An introduction to Dynamic Programming)
1.
的計画法入門
2.
目次 グラフの基礎知識 無向グラフ、有向グラフ
閉路、DAG、トポロジカル順序 グラフの表現方法 DAGの問題の解き方 最短経路、最長経路 最大/最小の重みの合計 連結しているか 動的計画法とDAG DAGを使った動的計画法 問題解説 DAGへの落とし方
3.
グラフの基礎知識
4.
グラフとは 丸が線で繋がれた図 丸に情報をいれ、線で情報のつながりを表す
丸に「駅名」、線で「電車でつながっている駅」を表す、 など
5.
グラフとは エッジ ノード エッジ ノード エッジ ノード エッジ ノード エッジ ノード エッジ 丸を「ノード」や「頂点」 線を「エッジ」や「辺」という
あるノードから別のノードに行く行き方を「パス」や 「経路」という エッジにも情報を持たせることがある。(重み)
6.
有向グラフ グラフの中で、一方通行なエッジがあるもの 一方通行のエッジがないものは「無向グラフ」
ノードから出て行くエッジを「出力辺」 ノードに入っていくエッジを「入力辺」 仕事順などを表せる 両方向通行可 の場合
7.
閉路 違うノードを通り、最初のノードに戻ることができる とき、その経路を「閉路」という。 つまり、一周回って戻ってこれる、ということ。 閉路あり 閉路あり 閉路なし!
8.
DAG 閉路を持たない有向グラフのこと 動的計画法のキモです これもDAG 閉路はない! つまりDAG これは違う
9.
トポロジカル順序 DAGにおいて、「ノードAからノードBにエッジがあ るとき、必ずAがBより前にあるように並び替えた順 序」のこと A B C トポロジカル順序は、
「A → B → C → D → E」 「A → B → D → C → E」 D E
10.
トポロジカル順序 トポロジカル順序は複数存在するときもある DAGを仕事の順序を表したグラフと考えると、 「仕事が成立する順序」とも考えられる。
トポロジカル順序にノードを並び替えることを 「トポロジカルソート」という。 A B C A → B → C → D → E または 仕事が成立する。 D E A → B → D → C → E なら
11.
グラフの表現(構造体) 構造体の配列での表現 typedef struct
_node { int data; //ノードの情報 } Node; typedef truct _edge { Node *pNode1; Node *pNode2; int weight; //重み } Edge; Node nodes[100]; Edge edges[10000]; 色々なグラフを表現可能。しかし若干めんどくさい。
12.
グラフの表現(配列) 配列での表現 int nodes[100]; int
nodes[10][20]; ノードが線、長方形、直方体状に並んだグラフを簡単に再 現できる エッジはプログラミングでどうにか表現する nodes[i] = nodes[i-3] + 2; // node iとnode i-3を関連付け 動的計画法の問題に適している ノードの番号(座標)も情報として活用できる 複雑なグラフは再現しにくい
13.
グラフの表現(配列)例 node i
と node i-3 を関連付けした場合 i: 0 1 2 3 4 5 6 このグラフはDAGです(トポロジカル順序はiの昇順) nodes[i] = nodes[i-3] + 2 とすれば、エッジの重み が2のDAGが完成
14.
DAGの問題の 解き方
15.
グラフを使った問題 グラフの問題には、例えば以下があります。 ノードAからノードBに行くとき、
通るエッジ数(ノード数)の最大/最小 通るエッジの重みの合計の最大/最小 総経路数(行き方の場合の数) ノードAとノードBがつながっているかどうか 実は、グラフが配列を使ったDAGの時は、これらの問 題は簡単に解くことができます
16.
配列DAGの問題を解く(1) ノードAからノードBまでのなんちゃら系は、まずト ポロジカル順序で調べていきます。 トポロジカル順序で調べているので、あるノードを調 べている時、そのノードにつながっている入力辺の先の ノード(入力ノード)はすでに調べているはずです。 入力辺 調べる対象 のノード これらは、もう調べられている つまり、値が確定している
17.
配列DAGの問題を解く(2) 次に、調べ終わっているノードの値から、調べている ノードの値を確定します。 通るエッジの重みの合計の最大/最小なら
あるノードに保存する情報は、「ノードAから、そのノー ドに至るまでの重みの合計の最大/最小」とする あるノードに至るまでの重みの最大/最小は、その入力 ノードの情報+エッジの重みの中で、最大/最小のもの 4 2 8 3 10 1 ←4+3、2+10、8+1の中で 最大/最小の値を書き込む
18.
配列DAGの問題を解く(3) 最大/最小を求めるときは、以下の式が便利です。 node[i] =
max(node[i],node[j]+edge_val); or node[i] = min(node[i],node[j]+edge_val); この式をiの全部の入力ノードjに対して実行します iは固定でjが変わっていき、node[i]を更新するイメージ 例えば、あるノードが、それより6つ前までのノード 全てとつながっている時は(範囲チェックは割愛) for(int k=1;k<=6;k++) { node[i] = min(node[i],node[i-k]+edge_val); } 最大/最小のエッジ数なら、重みを1で固定します
19.
配列DAGの問題を解く(4) ノードAからノードBまでの総経路数の問題ならもっ と話は簡単です。 ノードに保存する情報は「ノードAからそのノードま での総経路数」とします
ノードをトポロジカル順序で調べていきます 調べる内容は、ただ入力ノードの値を足すだけです。 「確率」も同様にして求められます。 ノードに確率を保存し、そのp倍を出力先ノードに足す 4 0.4 確率1/4 0.6 確率1/4 2 8 ↑4+2+8通り ↑0.4*1/4 + 0.6*1/4
20.
配列DAGの問題を解く(5) 「ノードAとノードBが連結しているか」も同じように考えます。 面倒臭かったら、経路数が0かどうかを調べても良いです
ノードに保存する情報は、ノードAとそのノードがつながってい るなら1、そうでないなら0とします ノードAはノードAと連結していると考えます。 ノードAの値は1、それ以外はとりあえず0 トポロジカル順序で考えた時、全ての入力ノードの内、一つでも 1があれば1、一つもなければ0としていきます 若干効率は悪いですが… 今回はこれで行きましょう 1 0 0 ←1があるので、 1を書き込みます
21.
配列DAGの問題を解く(6) 初期条件には注意が必要です。 最大を求める問題なら、最初から最大値が決定している ノード以外のノードの値は、-∞で初期化します
実際には-∞は入れられないので、-INTMAXで我慢します 最小ならば、+∞で初期化します 経路数なら、明らかなところを1で、そうでないところ を0で初期化します。 連結しているかどうかは、連結しているかどうかの対象 ノードの値を1に、それ以外を0に初期化します。
22.
配列DAGの問題を解く(7) 実際に考えてみましょう 線状に並んだ101個のノードが数直線上にある。これ らのノードは「素数個」後のノードと繋がっている
2個後、3個後、5個後、7個後、11個後…と隣接 範囲外のノードは繋がっていないと考える。 この時1個目のノードから101個目のノードに行く 行き方は何通りあるか 最小のエッジ数は何個か
23.
配列DAGの問題を解く(8) グラフ i: 0 1 2 トポロジカル順序はiの昇順 3 4 5
24.
配列DAGの問題を解く(9) 行き方 int nodes[101]
= {0}; //行き方を格納 int primes[25] = {2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71 ,73,79,83,89,97}; nodes[0] = 1; //0番に行く行き方だけは1 //トポロジカルソート順に調べる for(int i = 0; i < 101; i++) { for(int j = 0; j < 25; j++) { if (i – primes[j] >= 0) { //範囲チェック nodes[i] += node[i - primes[j]]; } } } std::cout << nodes[100] << std::endl;
25.
配列DAGの問題を解く(10) 最小のエッジ数 int nodes[101];
//最小のエッジ数を格納 int primes[25] = {2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71 ,73,79,83,89,97}; nodes[0] = 0; //0番は0個のエッジ数で到達できる for(int i = 1; i < 101; i++) nodes[i] = 10000000; //+∞ //トポロジカルソート順に調べる for(int i = 0; i < 101; i++) { for(int j = 0; j < 25; j++) { if (i – primes[j] >= 0) { //範囲チェック nodes[i] = min(nodes[i], nodes[i - primes[j]] + 1); } } } std::cout << nodes[100] << std::endl;
26.
動的計画法とDAG
27.
動的計画法とDAG すでに分かっている答えを組み合わせて、新しい答え を作っていく方法 具体的には、制約が簡単な問題の答えから、より難しい制 約の問題を解いていく。
DP(Dynamic Programming)と言われる 通常の調べ上げより処理が圧倒的に軽い(𝑎 𝑛 → 𝑛 𝑎 ) 動的計画法の問題は、基本的にDAGに落とせる DAGに落とせれば、先程の解法が使える 配列を使ったDAGに落とすことが多いが、その時の添 字も情報として活用する
28.
例題 100を素数の和で表すとき、その最小項数を求めよ 例:8
= 2+2+2+2 = 2+3+3 = 5+3 数は2 だから、最小項
29.
例題:ヒント 100を素数の和で表すとき、その最小項数を求めよ ターゲットの自然数をいきなり分解しようとすると難 しい。
とりあえず、DAGに落とせないか考えよう dp[i]に「iを素数の和で表すときの、最小項数」を入 れてみる。 なぜこの配列を考えようと思ったのかは、後解説します dp[i]とdp[i-素数]の関係を考えると…
30.
例題:解説 dp[i] :=
iを素数の和で表すときの、最小項数 足した素数分だけ右に行き、使ったエッジ数が1増える 「ノード0からノード100に行くときの、最小エッジ 数を求めよ」と同義 先ほどの問題と全く一緒 i: 0 1 2 3 4 5
31.
問1 100万円以下の金額が与えられる。10種類の小切手(𝑖 種類目の小切手の金額は𝐴[𝑖](> 0))で支払いをする時、 支払う合計枚数の最小値を出力しなさい。
出典:『最速最強アルゴリズマー養成講座』(編)
32.
問1:解説 dp[i] :=
i万円払うときの小切手の最小枚数 1枚使うごとに枚数が増える。iはA[i]だけ増える 「枚数」は「使ったエッジ数」に置き換えられる 例題と同じ!
33.
問2 将棋の「銀」の動きをするコマが、10*10の盤面の一 番左下にある。35ターンちょうどで、一番右上に行く 進み方は何通りあるか。
34.
問2:ヒント 地形がある問題は、その地形の形でノードを置くと良 いです。 dp[i][j]など。
その上でノードのつながりを考えます。今回は銀が移 動するので、左上、上、右上、右下、左下のノードと繋 がっていると考えられます しかしこれだとDAGになりません。こういう時はもう 一次元何かを増やすとうまくいくことが多いです。何か もう一つ制約は無かったでしょうか? 銀の動きをグラフに してみたがDAGにならない→
35.
問2:解説(1) 今回は、ターン数でもう一次元拡張します。 dp[i][j][k]
:=kターンで座標(i,j)に行く行き方 一回移動すると、ターンが1増えるのでノードを一階 層ずらしてつなぎます。 j 全てのノードが一階層下の 左上、上、右上、右下、左下 と繋がっている k i
36.
問2:解説2 「30ターンちょうどで」→ 「30階層目で」 求めるものは、「ノード(0,0,0) j から(9,9,35)に行く総経路数 を求めよ」と同義 k
これはDAGで、トポロジカル 順序はkの昇順 i
37.
問2:解説(3) int dp[10][10][36] =
{0}; //kターンで(i,j)に行く進み方の数 int dirX[5] = {-1,0,1,-1,1}; //銀の進む方向(x) int dirY[5] = {1,1,1,-1,-1}; //銀の進む方向(y) dp[0][0][0] = 1; for(int k = 1; k <= 35; k++) { //トポロジカル順序はkの昇順 for(int i = 0; i < 10; i++) { for(int j = 0; j < 10; j++) { for(int l=0;l<5;l++) { int px = i - dirX[l]; int py = j - dirY[l]; if(isIN(px,py)) { //範囲チェック dp[i][j][k]+=dp[px][py][k-1]; } } } } } std::cout << dp[9][9][35] << std::endl;
38.
問3 さいころを振って進むすごろくがある。ただし、ちょ うど6𝑛 マス(𝑛
> 0)進むと、スタートに戻される。20 回さいころを振ったとき、スタート地点から30マス以 上進んでいる確率を求めよ。 出典:『最速最強アルゴリズマー養成講座』(編)
39.
問3:ヒント 一応、すごろくなので、地形があります。 地形と言っても「何マス進んだか」の一直線ですが…
サイコロを振って進むので、各ノードは6つ先までの ノード全てとつながっていると言えます ただし、 6𝑛個目のノードにはつなぐときは、スタートに つなぎ変えます しかし、これではDAGになりません。何か制約を加え てDAGにしましょう。
40.
問3:解説(1) 「サイコロを振った回数」を加えて次元を拡張します dp[i][j]
:= i回サイコロを振った時jマス進んでいる確率 i階層目の各ノードは、i+1階層目の6つ先までのノー ドと繋がっている 6𝑛個目の場合は、i+1階層目のスタートにつなぎ替える。 ある一つのエッジを進む確率は、エッジの出処のノー ドの値の1/6 この値をエッジの先のノードに足していく。 ←1/3*0.4 + 1/3*0.6 0.4 ←1/3*0.4 + 1/3*0.6 0.6 ←1/3*0.4 + 1/3*0.6 皆確率1/3の時
41.
j 問3:解説(2) 0 1 i j: 2 3 4 5 6 7
42.
問3:解説(3) double dp[21][121]={0}; //i回サイコロを振ってjマス進む確率 dp[0][0]
= 1.0; //スタートマスの確率は1 for(int i = 1; i <= 20; i++) { //トポロジカル順序はiの昇順 dp[i][0] = 1.0 / 6.0; for(int j = 1; j < 121; j++) { if (j % 6 != 0) { for(int k = 1; k <= 6; k++) { if (j – k >= 0) { //範囲チェック dp[i][j] += dp[i-1][j-k]/6.0; } } } } } double ans=0.0; for(int j = 30; j < 121; j++) ans += dp[20][j]; std::cout << ans << std::endl;
43.
問4 ある大小バラバラの1000個以下のビー玉が与えられ る。ビー玉の重さが1~10の整数だとして、これを2人 で分けるとき、合計の重さを均等にすることが可能か求 めなさい 出典:『最速最強アルゴリズマー養成講座』
44.
問4:ヒント ビー玉の合計の重さをSとすると、Sが偶数でない場合 不可能。偶数の時、「何個かのビー玉を選んで、合計が S/2となる選び方が存在するか」と言い換えられる。 「~を選んで」の問題の場合、「~をi番目まで考慮し た時の」と機械的に1次元増やすとうまくいく。
これと、合計を配列の添字にすると…
45.
問4:解説(1) dp[i][j] :=
i個目のビー玉まで考慮した時、選んだビー 玉の重さの合計がjとなるか(1:可 0:不可) 「選択」を「 i個目の~まで考慮した時」とした時は、 選択肢の数だけ、エッジが出ます 今回は、選ぶか選ばないかの2つのエッジが出ます 選んだ場合は、i番目のビー玉の重さだけ右にズレて1階層下 のノードとつながります。選ばない場合は直下のノードとつ ながります。 後は、(0,0)のノードと(1000,S/2)のノードが連結し ているかという問題を解くだけです。 もう少し効率のよい方法もあるらしい
46.
問4:解説(2) j i ビー玉の 重さ2 ビー玉の 重さ1
47.
問4:解説(3) int dp[1001][5001] =
{0}; // i個目のビー玉まで考慮した時、選んだ ビー玉の重さの合計がjとなるか dp[0][0] = 1; int weight[1000]; //ビー玉の重さ int sum = 0; //ビー玉の重さの合計 for(int i = 0; i < 1000; i++) sum += weight[i]; if (sum % 2 == 0) { for(int i = 1; i <= 1000; i++) { //トポロジカル順序 for(int j = 0; j < 5001; j++) { if(j - A[i - 1] >= 0) { //範囲チェック dp[i][j] |= dp[i-1][j-A[i-1]]; } dp[i][j] |= dp[i-1][j]; } } } if (dp[1000][sum/2]) std::cout << “possible” << std::endl; else std::cout << “impossible” << std::endl;
48.
DAGへの落とし方(1) まず、問題に関わる制約を全て書き出します。 その制約を「dp配列の添字または値にするもの」と 「グラフのつながりを考えるために使用するもの」にグ ループ分けします
大まかには 範囲指定されている制約は配列の添字になりやすい 求めるものは、配列の値になりやすい その他、問題を解いていく途中に値がコロコロ変わるもの は配列の添字/値になりやすい 選択肢、地形も配列の添字になる それ以外はグラフのつながりを表すものになる
49.
DAGへの落とし方(2) 特に配列の添字になりやすいもの ターン数、日数、手数、(試行)回数
合計 地形 選択(「i番目まで考慮した時の~」に変更して添字に) 特にグラフのつながり方を表すものになりやすいもの 移動規則(広い意味での「座標」を移動させるルール) 恒等的に同じ中身の配列
50.
問1 100万円以下の金額が与えられる。10種類の小切手(𝑖種類 目の小切手の金額は𝐴[𝑖](> 0))で支払いをする時、支払う合 計枚数の最小値を出力しなさい。
dpの添字または値になるもの 金額…問題を解いていく途中にコロコロ変わる。また、範囲指 定がされていて、金額の合計と言い換えられる。 枚数…求めるものだから、dp配列の値になりやすい。コロコロ 変わる。 グラフのつながりを表すもの 小切手の金額の配列…問題文中は常に一定。金額の合計を移動 させるものと考えることができる 結果:dp[i] := i円払うのにかかる合計枚数の最小値
51.
問2 将棋の「銀」の動きをするコマが、10*10の盤面の一 番左下にある。30ターンちょうどで、一番右上に行く 進み方は何通りあるか。 dpの添字または値になるもの
盤面…立派な地形。添字になりやすい。 ターン…特に添字になりやすいものの代表。解いている途 中にコロコロかわり、30ターン以内という制限もある 通り…求めるものなので値になりやすい。 グラフのつながりを表すもの コマの動き…移動手段。地形とセットでよく出てくる。 結果:dp[i][j][k] := kターンで(i,j)に行く進み方の数
52.
問3 さいころを振って進むすごろくがある。ただし、ちょうど6𝑛 マ ス(𝑛
> 0)進むと、スタートに戻される。20回さいころを振ったと き、スタート地点から30マス以上進んでいる確率を求めよ。 dpの添字または値になるもの 回数…添字になりやすい典型です マス…基本的に、出た目の合計と考えられます。問題を解いている 途中にコロコロ変わり、範囲指定もあります。 確率…求めるものです。値になりやすいです。 グラフのつながりを表すもの さいころ…移動規則です。進んだマスを増やすものと考えられます。 問題文中は一定です。 戻る…さいころと同じで、移動規則です。 結果:dp[i][j] := i回さいころを振った時jマス進んでいる確率
53.
問4 ある大小バラバラの1000個以下のビー玉が与えられる。 ビー玉の重さが1~10の整数だとして、これを2人で分ける とき、合計の重さを均等にすることが可能か求めなさい dpの添字または値になるもの
ビー玉の個数…二人の内どちらかに振り分けると考えれば、選 択と考えられます。範囲指定もあります。添字です。 合計の重さ…「合計」です。添字になります。 グラフのつながりを表すもの ビー玉の重さ…問題を解く間一定です。合計の重さを移動させ るものと考えることができます 結果:dp[i][j] := i個目のビー玉まで考慮した時、合計の重 さがjとなるか
54.
参考文献等 「DPの話」 http://d.hatena.ne.jp/Tayama/20111210/132350209 2
DAGと動的計画法の関連についてわかりやすく、詳しく書いて あります。今回扱っていない高度な話題もたくさんあります。 「最速最強アルゴリズマー養成講座」 http://www.itmedia.co.jp/enterprise/articles/1005/15/n ews002_2.html 今回の問題の出典元です。 「プログラミングコンテスト チャレンジブック」 通称蟻本です。動的計画法含め、様々なアルゴリズムについて 幅広く解説されています。
55.
おわり ご清聴、ありがとうございました。
Download now