動態規劃分析總結——怎樣設計和實現動態規劃算法
阿新 • • 發佈:2017-05-05
基於 進一步 使用 sdn 能夠 疑惑 樓梯 -1 們的
當然,我們還能夠進一步精簡。只用兩個變量來保存前兩次的計算結果; 這個算法留待讀者自己去實現
weight=2, 1, 3, 2
value =3, 2, 4, 2
W=5
輸出=7
思考一:我們能夠採用窮舉法,列出n個物品的全部組合形式,從中選取符合條件的最大價值:
進行算法設計的時候,時常有這種體會:假設已經知道一道題目能夠用動態規劃求解,那麽非常easy找到對應的動態規劃算法並實現;動態規劃算法的難度不在於實現,而在於分析和設計—— 首先你得知道這道題目須要用動態規劃來求解。
本文,我們主要在分析動態規劃在算法分析設計和實現中的應用,解說動態規劃的原理、設計和實現。在非常多情況下,可能我們能直觀地想到動態規劃的算法。可是有些情況下動態規劃算法卻比較隱蔽。難以發現。
本文。主要為你解答這個最大的疑惑:什麽類型的問題能夠使用動態規劃算法?應該怎樣設計動態規劃算法?
動態規劃第一講——緩存與動態規劃一、緩存與動態規劃
分析:非常顯然,這道題的相應的數學表達式是F(n)=F(n-1) + F(n-2);當中F(1)=1, F(2)=2。
非常自然的狀況是,採用遞歸函數來求解:
int solution(int n){ if(n>0 && n<2) return n; return solution(n-1) + solution(n-2); }假設我們計算F(10), 先須要計算F(9) F(8); 可是我們計算F(9)的時候,又須要計算F(8),非常明顯,F(8)被計算了多次。存在反復計算;同理F(3)被反復計算的次數就很多其它了。算法分析與設計的核心在於 依據題目特點,降低反復計算。 在不改變算法結構的情況下。我們能夠做例如以下改進:
int dp[11]; int solution(int n){ if(n>0 && n<2) return n; if(dp[n]!=0) return dp[n]; dp[n] = solution(n-1) + solution(n-2); return dp[n]; }這是一種遞歸形似的寫法,進一步,我們能夠將遞歸去掉:
int solution(int n){ int dp[n+1]; dp[1]=1;dp[2]=2; for (i = 3; i <= n; ++i){ dp[n] = dp[n-1] + dp[n-2]; } return dp[n]; }
例二:01背包問題
有n個重量和價值分別為vector<int> weight, vector<int> value的物品;背包最大負重為W,求能用背包裝下的物品的最大價值?
輸入:n =4weight=2, 1, 3, 2
value =3, 2, 4, 2
W=5
輸出=7
思考一:我們能夠採用窮舉法,列出n個物品的全部組合形式,從中選取符合條件的最大價值:
採用窮舉法,必定須要可以舉出全部狀態,不重不漏;而怎樣窮舉,方法多種多樣,我們的任務是要窮舉有n個元素組成的全部子集。
而窮舉的方法主要有兩種—— 遞增式(舉出1~100之內的全部數字, 從1到100);和分治式的窮舉(比如舉出n個元素的集合。包括兩種—— 含有元素a和不含元素a的)。於是,我們基於窮舉法得到背包問題的第一種算法—— 遞歸與分治。
int rec(int i, int j){//從i到n號物品,選擇重量不大於j的物品的最大價值 int res; if(i==n){ res=0; } else if(j< w[i]){ res = rec(i+1, j); } else{ res = max(rec(i+1, j), rec(i+1, j-w[i])+v[i]); } return res; }
調用res(0, W), 就可以得到結果. 時間復雜度O(2^n);我們來分析一下遞歸調用的情況。
動態規劃分析總結——怎樣設計和實現動態規劃算法