SlideShare a Scribd company logo
競技プログラミング講義
#4 「動的計画法」
動的計画法
●

別名(通称) DP

●

頻出の技法

●

●

予選の 4 番に必ずといっていいほどよく出
る
これがマスターできれば一人前
復習ー全探索(再掲)
●

●

「再帰関数」なるものを使って「状態の遷
移」というものを考える方法のこと
例題として「ナップサック問題」というの
があった
ナップサック問題(再掲)
●

重さ W[i] と価値 V[i] が決まっている N 個の品物
がある。重さの総和が S を超えないように品物
を選んだときの、それらの品物の価値の総和の最
大値を求めよ。
1≦N≦20
1≦W[i],V[i]≦1,000,000
1≦S≦1,000,000

●

重さを値段、価値を美味しさにすると予算内で最
状態 (0,300)

  150 円    200 円 
  100P

250P

100 円
50P
状態 (0,300)

  150 円    200 円 
  100P

250P

100 円
50P
1 本目を選んだ→状態 (1,150)

  150 円    200 円 
  100P

250P

100 円
50P
2 本目を選ばなかった→状態 (2,150)

  150 円    200 円 
  100P

250P

100 円
50P
3 本目を選んだ→状態 (3,50)→ 終了

  150 円    200 円 
  100P

250P

100 円
50P
3 本目を選んだ→状態 (3,50)→ 終了

  150 円    200 円 
  100P

250P

100 円
50P
初期状態 0

0,300 P
初期状態 0P

       
0,300
選んだ

1,150

100
P

1 本目

選ばなかった

1,300

0P
初期状態 0P

       
0,300
選んだ

1,150
選んだ

2,-50

350
P

100
P

選ばなかった

100
2,150 P

2 本目

選ばなかった

1,300
選んだ

250
2,100 P

0P

選ばなかった

1,300

0P
初期状態 0P

       
0,300
1,150

選んだ
100P

選ばなかった

1,300

選んだ
選ばなかった
100P
350P

2,150

2,-50

選んだ 選ばなかった

3,50

150
P

100
3,150 P

3 本目
0P

選んだ
選ばなかった
250P

0P

1,300

2,100
選んだ 選ばなかった

300
3,0 P

選んだ

250
3,100P

選ばなかった

50P

3,50

0P

3,150
データの再利用
●

(3,150) という状態が二回現れている

●

同じ状態からは同じ状態遷移しかしない
→ それぞれの状態から遷移して得られるポ
イントの最大値はその状態によって一意に
決まる

●

これを利用すれば計算量を抑えることがで
きる
逆に
●

それぞれの状態まで遷移してきた時のポイ
ントの最大値はその状態によって一意に決
まる

●

これを再利用しても計算量を抑えられる

●

→ これが動的計画法

●

(色んな場合をまとめて考えている)
動的計画法の利点
●

●

計算量:それぞれの状態に対して最大一回
しか計算を行うことはないのでそれぞれの
状態に対する計算の量を P 、状態数を C
とすると O(CP)
動的計画法では再帰関数を使わなくても配
列を使うことで実現することができる
DP するために
●

初期状態

●

状態遷移
を考える
ナップサックでの例
●

●

状態は選択し終わった本数を i, 残りのお金
を M とすると (i,M)
これを二次元配列 DP[i][M] で表すことがで
きる
初期状態
●

●

(0,S) ・・・まだ一本も選んでおらず、使える
残りの重さが S
DP[0][S]=0
( まだ一本も選んでいないので手に入れた
ポイントも 0)
状態遷移
●

状態の遷移:
次を選ぶ場合…
DP[i+1][M+W[i]]=max( 〃 ,DP[i][M]+V[i]);
次を選ばない場合…
DP[i+1][M]=max( 〃 ,DP[i][M]);
DP の流れ
●

これを i の小さい方から更新していく

●

最終的な答えは
max(DP[n][k]) (k=0...S) が答え
コード例
注意点
●

これでうまくいったのは、 i+1 本目を見て
いるとき、 DP[i][k] がすでに確定している
(その後に更新されることはない)から
= i が更新ごとに単調に増加しているから

●

●

後の結果が前の結果に影響するような場合
には DP を使うのは難しい
選ぶ順番によって結果が変わらないような
場合は前から見ていくことで適用できる
DP のコツ
●

更新していく順番を決めることができる
→DP が使える

●

状態を決める

●

初期状態を考える

●

状態遷移を考える

●

計算量は大丈夫か?
→ 実装
お分かりいただけただろうか…
説明だけでは分かりにくい
と思うので
●

実装しましょう

●

まずは典型問題から
〜実装タイム〜
NPCA Judge 「何通り?」
ヒント
●

更新していく順番は?
→ 左や下にいくことはない
ヒント
●

更新していく順番は?
→ 左や下にいくことはない
→ 左の下から右の上に更新していくことが
できる(右・上はどちらでもよい)

●

状態は?
ヒント
●

更新していく順番は?
→ 左や下にいくことはない
→ 左の下から右の上に更新していくことが
できる(右・上はどちらでもよい)

●

状態は?
→(i,j) 下から i 列目左から j 行目のマスに行
く場合の数
ヒント
●

初期状態は?
ヒント
●

初期状態は?
→ 最初は (0,0) にいるので dp[0][0]=1
ヒント
●

初期状態は?
→ 最初は (0,0) にいるので dp[0][0]=1

●

状態遷移は?
ヒント
●

初期状態は?
→ 最初は (0,0) にいるので dp[0][0]=1

●

状態遷移は?
→ dp[i+1][j]+=dp[i][j]

dp[i][j+1]+=dp[i][j]
ヒント
●

初期状態は?
→ 最初は (0,0) にいるので dp[0][0]=1

●

状態遷移は?
→ dp[i+1][j]+=dp[i][j]

●

計算量は?

dp[i][j+1]+=dp[i][j]
ヒント
●

初期状態は?
→ 最初は (0,0) にいるので dp[0][0]=1

●

状態遷移は?
→ dp[i+1][j]+=dp[i][j]

●

計算量は?
→O(W*H*2) = O(WH)

dp[i][j+1]+=dp[i][j]
解法
●

dp[0][0]=1

●

i を 1~W,j を 1~H でループさせて
dp[i][j]=dp[i+1][j]
dp[i][j+1]=dp[i][j]
としながら更新していく

●

答えは dp[W-1][H-1]
〜実装タイム〜
NPCA Judge 「部分和問題」
ヒント
●

更新していく順番は?
→ 和に順番は関係ないので、前から見て行
ってよい
ヒント
●

更新していく順番は?
→ 和に順番は関係ないので、前から見て行
ってよい

●

状態は?
ヒント
●

更新していく順番は?
→ 和に順番は関係ないので、前から見て行
ってよい

●

状態は?
→ (i,j) i 個選び終わったときに和を j にでき
るかどうか
→ 数は全て正なので和は 10000 までとっ
ておけばよい
ヒント
●

初期状態は?
ヒント
●

初期状態は?
→ 最初は 0 個見終わっていて、和が 0
→ dp[0][0]=True
ヒント
●

初期状態は?
→ 最初は 0 個見終わっていて、和が 0
→ dp[0][0]=True

●

状態遷移は?
dp[i+1][s+a[i]]=dp[i][s]
dp[i+1][s]=dp[i][s]
ヒント
●

初期状態は?
→ 最初は 0 個見終わっていて、和が 0
→ dp[0][0]=True

●

状態遷移は?
dp[i+1][s+a[i]]=dp[i][s]
dp[i+1][s]=dp[i][s]

●

計算量は?
ヒント
●

初期状態は?
→ 最初は 0 個見終わっていて、和が 0
→ dp[0][0]=True

●

状態遷移は?
dp[i+1][s+a[i]]=dp[i][s]
dp[i+1][s]=dp[i][s]

●

計算量は? → O(N*S*2) = O(NS)
〜実装タイム〜
AOJ0557 「 1 年生」
ヒント
●

大体ナップサック
dp マスターへの道のり
・どんな状態を考えるか
・状態遷移はどうなるか
を考えるのが難しい
●

●

●

慣れも必要
これをある程度マスターすれば予選通過は
かなり見えてくる
問題を解いて慣れましょう
練習問題
●

メーリングリスト参照

More Related Content

More from Ryunosuke Iwai

Rth number
Rth numberRth number
Rth number
Ryunosuke Iwai
 
Glasses
GlassesGlasses
Ice
IceIce
Water flow
Water flowWater flow
Water flow
Ryunosuke Iwai
 
文字列処理
文字列処理文字列処理
文字列処理
Ryunosuke Iwai
 

More from Ryunosuke Iwai (7)

Rth number
Rth numberRth number
Rth number
 
Glasses
GlassesGlasses
Glasses
 
Ice
IceIce
Ice
 
Water flow
Water flowWater flow
Water flow
 
文字列処理
文字列処理文字列処理
文字列処理
 
データ処理
データ処理データ処理
データ処理
 
Arduino
ArduinoArduino
Arduino
 

DP