動態規劃 0 1揹包問題

2021-07-31 21:47:27 字數 1756 閱讀 6313

0-1揹包問題是比較經典的動態規劃,題意如下:

給定n件物品的重量和對應價值,給定乙個揹包的最大承重,求該揹包所能裝下的物品的最大價值,並輸出哪幾件裝進了揹包。

這個問題可以用乙個二維陣列來做,這樣非常直觀明了。但是有些情況下,資料過大,採用二維陣列會超空間,所以需要採用一維陣列進行空間壓縮,複雜度是不變的,要注意的是填充一維陣列時需要倒序。每次更新一遍一維陣列,其實就相當於二維陣列的更新。

下面是二維陣列的方法,一維陣列的方法在其後:

最關鍵的乙個公式是

d[i][j] = max(d[i - 1][j], d[i - 1][j - w[i]] + v[i]);

其中,d[i][j]是指在前i件物品中,選擇若干件放在承重為j的揹包中,可以取得的最大價值。

先給出d[i][j]這個矩陣的示意圖,因為我覺得在程式設計實現

過程中一直想著這個矩陣,思路會清晰很多。

這裡,我統一把陣列的第0個元素置為零,不使用(即:在上面的矩陣中,第0列全是0,不使用,就沒有畫出來。陣列中的1就代表第乙個)

**如下,注釋說的很清楚了:

#include 

#include

using

namespace

std;

//d[i][j]是乙個矩陣,表示在前i件物品中,選擇若干件放在承重為j的揹包中,可以取得的最大價值

int main(); //6件物品的重量

int v[6] = ; //6件物品的價值

int c = 10; //揹包的最大承重量

int a[6] = ; //用來儲存第i個物品是否裝入揹包

int d[6][11] = ; //矩陣

//接下來的雙層for迴圈,用來填充矩陣

for (int j = 0; j <= 10; j++)

d[0][j] = 0;

for (int i = 1; i <= 5; i++)

else}}

//接下來的for迴圈,用來回溯,找到哪個物品放入了揹包

int j = 10;

for (int i = 5; i > 0; i--)

else

a[i] = 0;

}cout

<< d[5][10] << endl;

for (int i = 1; i <= 5; i++)

cout

<< a[i] << " ";

cout

<< endl;

return

0;}

填充乙個一維陣列的過程其實就是更新n遍,第i遍更新相當於上面的前i個物品容量不同時的最大價值。

下面是**:

#include 

#include

#include

#include

using

namespace

std;

int main(); //6件物品的重量

int v[6] = ; //6件物品的價值

int c = 10; //揹包的最大承重量

int dp[11] = ;

for (int i = 0; i < 6; i++)

}cout

<< dp[c] << endl;

return

0;}

動態規劃揹包問題 01揹包

問題描述 n種物品,每種乙個。第i種物品的體積為vi,重量為wi。選一些物品裝到容量為c的揹包,使得揹包內物品不超過c的前提下,重量最大。問題分析 宣告乙個f n c 的陣列。f i j 表示把前i件物品都裝到容量為j的揹包所獲得的最大重量。當 j v i 時,揹包容量不足以放下第 i 件物品,f ...

動態規劃 揹包問題 01揹包

有n種物品和乙個容量為v的揹包,每種物品僅用一次。第i件物品的費用是w i 價值是v i 求解將哪些物品裝入揹包可使價值總和最大。例如 n 5,v 10 重量 價值 第乙個物品 10 5 第二個物品 1 4 第三個物品 2 3 第四個物品 3 2 第五個物品 4 1 首先我們考慮貪心策略,選取最大價...

0 1揹包問題(動態規劃)

一 問題描述 有n件物品和乙個容量為v的揹包。第i件物品的費用是c i 價值是w i 求解將哪些物品裝入揹包可使價值總和最大。所謂01揹包,表示每乙個物品只有乙個,要麼裝入,要麼不裝入。二 解決方案 考慮使用動態規劃求解,定義乙個遞迴式 opt i v 表示前i個物品,在揹包容量大小為v的情況下,最...