如何從動態規劃的角度去看問題

算法導論(MIT 6.006 第19講)算法

動態規劃的核心處理流程是什麼?

1: 定義子問題spa

計算子問題的數量

2:猜想(嘗試全部可能的方式,獲取最好的)code

計算選擇的數量

3: 關聯全部的子問題排序

計算單個子問題所須要處理的時間

4: 重用子問題結果並記下新的結果,或者使用DP的bottom-up方式(須要注意沒有環)遞歸

計算總耗時

5: 解決原有的問題圖片

對結果進行組合等等會劃掉部分額外的時間

總的來講就是:嘗試全部可能的子問題的結果,將最好的可能子結果存儲下來,而後重複利用已經解決的子問題,遞歸去解決全部的問題(猜想+記憶+遞歸)it

它消耗的時間爲: 子問題的數量 * 每一個子問題處理所須要時間

例1:斐波那契數列

使用遞歸的方式求斐波那契數列

fib(n):
    if n<=2:f=1;
    else: f= fib(n-1)+fib(n-2);
    return f;

這種方式的運行時間爲 $\theta$($2^{n/2}$),空間爲O(1)table

T(n)=T(n-1)+T(n-2)+O(1) $\geq$ 2T(n-2)= $\theta$($2^{n/2}$)

Memoized DP 算法求斐波那契數列

fib(n):
    memo={}
    if n in memo:return memo[n];
    if n<=2:f=1;
    else f=fib(n-1)+fib(n-2);
    memo[n]=f;
    return f;

這種方式的運行時間爲$\theta(n)$,空間爲O(n)class

memo的存在使得實際產生調用的只有 fib(1) .... fib(n),共n次,區域的直接從memo中獲取,使用常量的時間

Bottom-up DP算法求斐波那契數列

fib(n):
    fib={}
    for i in range(1,n+1):
        if i<=2: f=1
        else: f=fib[i-1]+fib[i-2]
        fib[i]=f
    return fib[n]

這種方式的運行時間爲$\theta(n)$,空間能夠只用O(1)循環

它能夠看作是一種拓撲排序(針對DAG),對於使用空間其實只須要記住前兩個便可
圖片描述

例2:最短路徑

要求s到t的最短路徑,那麼一定會通過與t相鄰的一條邊,如圖示的u,那麼最短路徑$\delta(s,t)$=$min_{(u,t)\in E}(\delta(s,u)+w(u,t))$

$\delta(s,u)$就是須要遞歸調用處理的部分

對於DAG:$\delta(s,t)$每一個子問題的處理時間爲 indegree(t)+O(1)

indegree(t):入度數也就是相似(u,t)邊的數量,須要去遍歷全部t的入邊

O(1):判斷是否是有入邊

總共的執行時間爲
$$\sum_{v\in V}(indegree(v)+O(1))=O(E+V)$$
圖片描述

當圖中有環的時候求最短路徑產生的問題

要求s到v的最短路徑 $\delta(s,v)$,首選須要去求 $\delta(s,a)$,而後是$\delta(s,b)$,到b節點有兩條路徑:$\delta(s,s)$和$\delta(s,v)$,此時去memo中查$\delta(s,v)$是不存在的,又會這回查詢,致使了一個死循環
圖片描述

解決圖中有環的時候求最短路徑的問題

方式是去環,將原來的圖一層一層的展開。
假設從s到v須要的路徑爲k步,那麼能夠獲得 $\delta_k(s,v)$=$min_{(b,v)\in E}(\delta_{k-1}(s,b)+w(b,v))$,當k遞減到0的時候,其實也就是從s到s自己
圖片描述
所須要的展開層數爲:|V|-1

對於求最短路徑來說,最長不能超過|V|-1,不然就是成環,會形成循環的狀況(從0開始的計數),這就是爲何Bellman-Ford的外層循環是 |V|-1

每層的節點數爲全部的節點。那麼總共的節點數爲|V'|=|V|(|V|-1)+1=O($V^2$),邊數是|E'|=|E|(|V|-2)+1=O(VE)。轉換後的圖是DAG圖,那麼實際上的時間爲O(V'+E')=O(VE)。這也就是從動態規劃的角度去看Bellman-Ford算法

節點的數目是1個源點,邊的數目是每多一層實際上就多了加了一遍全部的邊。

斐波那契數列與最短路徑使用動態規劃處理步驟的對比

例子 斐波那契數列 最短路徑
1:定義子問題 $F_k$ 其中$1\leq k \leq n$ $\delta_k(s,v)$ 其中 $v\in V, 0\leq k < V $
子問題數量 n $V^2$
2:猜想 什麼都沒作,徹底是定義 節點v的入邊(若是存在的話)
選擇的數量 1 v的入邊數+1
3:關聯全部的子問題 $F_k=F_{k-1}+F_{k-2}$ $\delta_k(s,v) =min_{(u,v)\in E}(\delta_{k-1}(s,u)+w(u,v))$
子問題的時間 $\theta(1)$ $\theta(1+入度(v))$
4:重用子問題結果並記下新的結果 for k=1,..,n for k=0,1,..,V-1
總共耗時 $\theta(n)$ $\theta(VE)+\theta(V^2)$ (若是存在入度,就有後項)
5:解決原有的問題 $F_n$ $\delta_{v-1}(s,v) ,v \in V$
額外耗時 $\theta(1)$ $\theta(V)$(Bellman-Ford最後的遍歷)
相關文章
相關標籤/搜索