本文通過01揹包問題引入動態規劃,來介紹各種揹包與初等動態規劃問題,持續更新中...
問題概述:有n個重量和價值分別為\(w_i\)和\(v_i\)的物品。從這些物品中挑選出總重量不超過\(w\)的物品,求所有挑選方案中價值總和的最大值。(下標從1開始)
樣例:
\[input:n = 4,w = 10,(w,v) =
\]\[output:12(選擇2,4號物品)
\]思路引入:我們最容易想到的方案是暴力搜尋,即對所有物品是否放入揹包進行搜尋。**如下:
int n, w;
int v[maxn], w[maxn];
//從第i個物品開始挑選總重量小於j的部分
int dfs(int i, int j)
但這種方案搜尋深度為n,最壞需要\(o(2^n)\)的時間複雜度,如何優化呢?
我們建立遞迴樹可以看到,dfs以(3,2)為引數呼叫了兩次。如果引數相同,則返回結果一定相同。我們可以很容易的想到用乙個陣列來記錄已經被算出來的部分,從而避免相同引數計算多次的情況。這裡我們用資料dp來記錄已經被求解的部分。**如下:
int n, w;
int v[maxn], w[maxn], dp[maxn][maxn];
//從第i個物品開始挑選總重量小於j的部分
int dfs(int i, int j)
int main()
這種稱為記憶化搜尋,接下來我們可以利用記憶化搜尋,來引入一定的遞推式,利用遞推式來求解問題的思路則為動態規劃(dp:dynamic programming)。
動態規劃解決方案:我們設\(dp[i][j]\)表示為從前i個物品中挑選,放入最大容量為j的揹包中所能得到的最大價值。對於每個物品,只有拿與不拿兩種情況(即0與1),根據此思路可得如下遞推式:
\[dp[i][j] = \begin
dp[i-1][j] & j \le w[i] \quad 剩餘空間j無法放下物品i \\
max(dp[i-1][j],dp[i-1][j-w[i]]+v[i]) & j \ge w[i] \quad 剩餘空間j可以放下物品i,則取不選與選的較大值
\end
\]根據規律可得下表:
牆裂建議親自動手推表!!!
**如下:
#include#includeusing namespace std;
typedef long long ll;
const int maxn = 2e3 + 5;
int n, w;
int v[maxn], w[maxn], dp[maxn][maxn];
int main()
滾動陣列優化:我們可以從遞推式中發現,dp[i]的所有數隻和dp[i-1]有關,和dp[i-2],dp[i-3]等沒有任何關係。我們可以想到:去掉陣列第1維,對於第n次dp陣列更新來說,在更新之前,dp[1..w]儲存的是第n-1次更新中已經更新完的資料。可得:
\[dp[j] = \begin
dp[j] & j \le w[i] \quad 剩餘空間j無法放下物品i \\
max(dp[j],dp[j-w[i]]+v[i]) & j \ge w[i] \quad 剩餘空間j可以放下物品i,則取不選與選的較大值
\end
\]化簡得:
\[dp[j] = max(dp[j],dp[j-w[i]]+v[i]) \quad j \ge w[i] \quad 剩餘空間j可以放下物品i,則取不選與選的較大值
\]但是我們需要注意,j的遍歷需要逆序進行!。原因是:如果正序進行,第n次dp陣列更新會覆蓋掉第n-1次dp陣列更新,例如遍歷完dp[3]時,此時的dp[3]若被更新,則是選擇了第n號物品,但是後續更新需要的是第n-1輪更新所得的dp陣列,違背了第n輪更新只需要第n-1輪更新的原則。可得如下**:
#include#includeusing namespace std;
typedef long long ll;
const int maxn = 2e3 + 5;
int n, w;
int v[maxn], w[maxn], dp[maxn];
int main()
動態規劃入門
1 用 dp 做的題大多數返回值是int boolean,求max min,不能打亂原來輸入順序。2 動態規劃有兩個重要定義,乙個叫 optimal substructure 另乙個叫 overlap subproblem 各種排序 tree 類問題中,都會用到 divide conquer 的思想...
動態規劃入門
大家可以看看這篇文章dp,哪個更容易理解就看哪個!一 動態規劃的定義 動態規劃程式設計是一種針對於解決最優化問題的一種途徑 一種方法,而不是一種特殊演算法,也就是說它沒有固定的模板。在動態規劃中,每走一步都要看看能不能最優,而且動態規劃最擅長的就是多階段問題!二 動態規劃的基本概和基本模型構成 1....
動態規劃入門
學動態規劃自然要從數字三角形開始起步,那麼我們就先從數字三角形開始。數字三角形題目 有乙個由非負整數組成的三角形,第一行只有乙個數,除了最下行之外的每個數的左下方和右下方各有乙個數,如下圖所示 3 24 10 1 4 3 2 20 從第一行的數開始,每次可以往下或往右下走一格,直到走到最下行,把沿途...