イントロダクション
動的計画法(Dynamic Programing:以下「DP」と記述)は,ある種の最適化問題を効率的に(少ない計算時間で)解くための方法である。
アルゴリズム関連の参考書籍では,次のように説明される。
k 個の要素だけをとったときの最適解が表の形で与えられているとする。これに要素を1個付け加えたときに,最適解がどのように変わるかをこの表をもとに計算し,表を書き換える。
この操作を続けて,n 個の要素すべてを使った最適解が求まればよい。表の添え字としては,問題の性格を規定するパラメータのうち要素の個数以外のものを選ぶ。
問題を細かく小さい問題に分けて,それぞれにベストの解答を見つけよ。それらの回答を張り合わせて,全体の問題の回答を導け。
DPをインターネットで検索して得られる情報も概ねこのような説明であると思う。これらの説明と,いくつかの例題を見ることでDPのやりたいこと(方法)を(ある程度)理解することはできるであろう
しかしながら,実際に問題の解法としてDPを適用しようとした場合,「何を“小さい問題”として定義するのか?」,「何を“(k 個の)要素”とするのか?」を考え付くことが難しく(そもそもDPで解くべき問題であるかも見抜けないことも多い),解を得るまでに至らないのである。
ここでは,DPを数学面から見直し*1,各種例題を数学的に捉えなおすことでDPの理解を深める。「DPで考える」ための考え方を習得することを目指す。
DPの数学表現
動的計画法は「離散値を取る変数で表される関数の最大値または最小値(最適値)」を効率的に求める方法である。
変数 xi が 離散値{ a1,a2,・・・,an }をとるとき,
一般的には,この関数の最適値を求めるには xi の全ての組み合わせについて関数の評価を行わなければならない。しかしながら,関数 f が次のような形で表されるとき,全件評価を行わずに最適値を求める方法が存在する。
x1 に着目すると, x1 は f1(x1),h1(x1,x2) にのみに関係する。変数 x2 に対して,f1(x1)+h1(x1,x2)の最大値を値とする関数f2(x2)を考える。
続いて式(2)について同様に,変数x3に対して,f2(x2)+h2(x2,x3)の最大値を値とする関数f3(x3)を考える。
以下,同様の式の置きかけを続けることで,最終的には関数fn(xn)を次のように導くことができる。
上述の説明は“最大値/max”を“最小値/min”に言い換えても成立する。(関数値の最小値を求めるときにも使える)
DPの計算手順は次の通りとなる。
関数f1(x1),hi(xi,xi+1) (i=1,n-1)が与えられたとき
1. f2 = max(f1(x1)+h1(x1,x2))を求める。
x1, x2は離散値なので,f2(x2)も離散値となる。==> 配列へ保存
f2(x2)の値を用いて,
2. f3 = max(f2(x2)+h2(x2,x3))を求める。以下,f4,f5と求め,最終的には fnを求める。
fn の最大値が式(1)の最大値となる。
DPの適用
変数xi, xi+1を“問題”で定義される何らかの状態を表す値として捉えると,hi(xi,xi+1) は現在の状態 xi から次の状態 xi+1 へ遷移すると得られる値(得点)として考えられる。
DPは,この状態を進めることで得られる値(得点)の和について,その最適値を求める問題に適用することができる。
最適値に対応する各変数の値
式(1)が最適値をとるときの変数 xi の値が必要な場合には,次のように求める。
変数 xi+1 の関数,
fn(xn) の最大値(pnとする)が求まると,mn-1(pn) から xn-1 の値が求まる。これをpn-1とする。 以下,同様にmn-2(pn-1) から pn-2 を求め,pn-3,pn-4,・・・を順番に求める。pi が xi の値である。
例題1
TopCoder Tutorialから
http://www.topcoder.com/tc?module=Static&d1=tutorials&d2=dynProg
このTutorialのIntermediateの問題では,次の例題が挙がっている。
N×Mの表の各マスに,それぞれいくつかのリンゴが置かれている。左上のマスからスタートして,右もしくは下へ進み,通ったマスのリンゴを集めながら右下のマスまで行く。リンゴは最大で何個集められるか?
マスを進む各ステップ(1ステップで1マス移動)の状態(状態=どのマスの上にいるか)を x0, x1, ・・・, xN+M-2 とする。i ステップ目にいるマス xi は,左上のマスを(0,0),右下のマスを(N-1, M-1)とする座標系を考えたとき,(p, q) :p+q=i のマスとなる。 x0は左上のマスであり,xN-1+M-1 は右下のマスである。
この最適化(最大値)問題は,xi における獲得リンゴ数を f(xi) とすれば,
ここで,xi と xi+1 の間には進む方向に関するルールからの依存関係があることに注意が必要である。
xi 上のマス(p, q)は,xi-1 においてマス (p-1, q),もしくは(p, q-1) のときのみ移動可能である。
ここで次の関数h(xi,xi+1)を考える。
進む方向の依存関係を考慮した獲得リンゴ数の式は次のように書くことができる。
この式は前述の式(1)と同等の形式であり,DPを用いて最大値を計算することができる。f1(x1)を次のように定義すると,
例題2
有向グラフの経路最適化問題を考える。
各枝は2頂点 xi と xi+1 を結ぶものであるので,枝の得点は次のように表すことができる。
SからEまでの経路で得られる得点は次のように書き表せる。
ここで,グラフの枝ではなく頂点に得点が与えられているケースを考える。この場合は,各ステップ i において,頂点 xi のうち最大値をとる頂点を訪問すれば良いことは自明である。このケースは各ステップで最大となるものを選択していく“貪欲法”となる。
動的計画法は,あるステップの値が1つ前のステップの状態に依存するよう定義されるときに,それらの値の組み合わせ(これまでの例では加算)を最適化するときに用いることができると捉えることができる。
*1参考文献:これなら分かる最適化数学―基礎原理から計算手法まで