求解方法
標準的01揹包問題是指,有n(int型)個物品和最多裝重量w(int型)的揹包。weight陣列表示物品的重量,即weight[i]表示第i個物品的重量;value陣列表示物品的價值,即value[i]表示第i個物品的價值。問把哪些物品裝入揹包使得物品價值總和最大,每個物品只能裝一次。
舉例1,假設揹包重量為4,物品資訊由**描述:
重量價值
物品01
15物品1320
物品24
30如果遇到的問題符合01揹包的特點,可以思考是否能轉化為01揹包問題
每個物品要麼取,要麼不取,用回溯法搜尋所有情況,時間複雜度o(2^n)
用動態規劃方法,以五個步驟來解決問題。以下都是針對例子1用二維dp陣列描述
第一步確定dp陣列含義
dp陣列如圖所示
dp[i][j]表示從下標為[0~i]的物品任意取,放入容量為j的揹包,價值總和最大值
i表示物品,j表示容量
第二步確定遞推公式
只有兩個方向可以推出dp[i][j]
所以遞推公式為
dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - weight[i]] + value[i])第三步初始化
dp陣列初始化不能違背dp陣列的定義
由dp陣列遞推公式知。推導dp陣列即要用到dp陣列前一行的值,也要用到前列的值,因此初始化dp陣列第一行和第一列
第一列時揹包容量為0,因此全初始化為0,即dp[i][0]=0,i為0~n-1
第一行時只能選擇物品0,揹包容量逐漸增加到w。因此dp[0][j]中,容量j大於等於物品0的重量weight[0]時,dp[0][j]為物品0的價值,j小於其時為0。
所以初始化第一行時,遵循遞推公式的正序遍歷,**有兩次迴圈,要想只有一次迴圈,應採用倒序遍歷
for (int j = w; j >= weight[0]; j--)
迴圈遍歷初始化時,**也要遵循遞推公式,但是正序遍歷,會把物品0加入多次
for (int j = weight[0]; j <= w; j++)
第四步確定遍歷順序
第三步初始化的dp陣列如下
有兩個遍歷維度:物品和揹包重量,因此有兩層for迴圈
這裡先遍歷物品或先遍歷揹包重量都可以,但先遍歷物品更好理解
for(int i = 1; i < n; i++)
}
第五步推導dp陣列
最終的dp陣列結果如下
最終結果就是dp[2][4]
如果修改遍歷時的判斷條件:
if (j - weight[i] >= 0)
dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - weight[i]] + value[i]);
dp陣列變成:
完整**如下:
vectorweight = ;
vectorvalue = ;
int w = 4; //揹包重量
int n = 3; //物品數量
// 二維陣列
vector> dp(n + 1, vector(w + 1, 0));
// 初始化
for (int j = w; j >= weight[0]; j--)
// weight陣列的大小 就是物品個數
for(int i = 1; i < n; i++)
cout << dp[n][w]優化方法
可以用一維dp陣列(滾動陣列)解決01揹包問題
因為發現上一行的資料可以重複利用,推導的第一種dp陣列上一行的資料是直接拷貝到下一行
因此可以把dp陣列壓縮成一維陣列:
dp : [0, 15, 15, 20, 35]
dp[j]表示容量為j的揹包,所背的物品價值可以最大為dp[j]。
其遞推公式是
dp[j] = max(dp[j], dp[j - weight[i]] + value[i]);
需要注意的是,一維dp陣列的遍歷順序是揹包容量從大到小,為了保證每個物品只放入一次
所以遍歷順序只能是先遍歷物品再遍歷揹包容量
vectorweight = ;
vectorvalue = ;
int w = 4; //揹包重量
int n = 3; //物品數量
// 初始化
vectordp(w + 1, 0);
for(int i = 0; i < n; i++)
}cout << dp[w] << endl;
演算法筆記 動態規劃1
動態規劃適合求解最優問題,比如最大值最小值等。它可以顯著的降低時間複雜度,提高 的執行效率。0 1 揹包問題 在上篇總結中,用回溯演算法解決了 0 1揹包問題。但是,在求解的過程中,我們應該能想象的出,有些步驟是一直在重複執行。如果揹包的總載重為 9 物品個數為 5 質量分別為 2,2,4,6,3 ...
演算法 動態規劃(1)
把問題拆分成若干個子問題,類似遞迴 分治 但是動規多用於處理最優解,有重疊子問題的問題,因為動態規劃對於重疊子問題不會反覆計算,會建立一張表將之前計算過的子問題答案直接儲存,避免了重複計算,加快計算速度 練習1 有8個任務,每個任務完成需要一定的時間,完成之後就會有相應的報酬 圖上的紅色字段 但是任...
演算法1 動態規劃
動態規劃的步驟是 1.找出最優解的特徵,並刻畫其結構特徵 2.遞迴地定義最優值 3.以自底向上的方式計算出最優值 4.根據計算最優值的時得到的資訊,構造最優解。動態規劃演算法的有效性依賴於兩個最重要的性質 最優子結構性質和重疊子問題性質。栗子1,矩陣連乘問題。1 動態規劃 矩陣連乘問題 2 incl...