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的情況下,最...