演算法筆記 動態規劃 1

2021-10-20 09:16:23 字數 2837 閱讀 1637

求解方法

標準的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...