揹包問題詳解(c ) 01揹包

2021-10-03 04:49:34 字數 1364 閱讀 8477

有 n 件物品和乙個容量是 v 的揹包。每件物品只能使用一次。第 i件物品的體積是 v,價值是 wi。

求解將哪些物品裝入揹包,可使這些物品的總體積不超過揹包容量,且總價值最大。

輸出最大價值。

第一行兩個整數 n,v用空格隔開,分別表示物品數量和揹包容積。接下來有 n 行,每行兩個整數 vi,wi用空格隔開,分別表示第 i件物品的體積和價值。

每種物品只有一件,可以選擇放和不放。那麼我們很容易利用動態規劃思想得到狀態轉移方程:

f[i][j]=max // f[i][j]表示前i件物品恰放入乙個容量為j的揹包可以獲得的最大價值。
有了狀態轉移方程,我們可以直接寫出01揹包問題二維陣列的解法。

#include#includeusing namespace std;

const int n = 1010;

int n,m;

int v[n],w[n];

int f[n][n];

int main()

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

}cout《該方法的時間與空間複雜度均為o(nm)。,時間複雜度已經無法優化了,空間複雜度可以繼續優化到o(n),這裡我們觀察狀態轉移方程可以得知,f[i]只與f[i-1] 有關。那麼我們可以只使用乙個一維的陣列f[0…v]來表示f[i][0…v],狀態轉移方程為:

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

為了使 一維轉移方程 max(f[j],f[j-v[i]]+w[i]) 與二維的狀態轉移方程 max相對應,我們需要將揹包大小m從大到小列舉,而不是順序列舉。why?為什麼要逆序列舉,大家可以看這篇文章

或者自己模擬一下資料,用順序列舉的方式推一篇,也就很容易明白了。

下面是01揹包一維陣列優化的**:

// 一維陣列優化版

#include#includeusing namespace std;

const int n =1010;

int n,m;

int v[n],w[n];

int f[n];

int main()

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

}cout《我們可以直接得到01揹包問題的模板

//m為揹包大小.cost為代價,weight為價值

void zeroonepack(int cost,int weight)

揹包問題還可能有一些變種的問法,有的要求恰好裝滿揹包,有的沒有要求.這兩種的初始化是不同的。如果需要恰好裝滿揹包,那麼初始化時除了f[0]為0其它f[1…v]均設為-∞,沒有要求恰好裝滿的話,初始化時應該將f[0…v]全部設為0。

C 0 1揹包問題

0 1揹包問題 0 1揹包問題基本思想 p i,j 表示在前面i個物品總價值為j時的價值最大值。str i,j 表示在前面i個物品總價值為j時的價值最大值時的物品重量串。i 0 或者j 0時 p i,j 0 str i,j 第i件物品的在重量小於j時能夠放入揹包 p i,j p i 1,j w i ...

C 01揹包問題

01揹包問題 有n個重量和價值分別為wi,vi的物品。從這些物品中挑選出總重量不超過w的物品,求所有挑選方案中價值總和的最大值 輸入格式 nw v w輸出格式 價值總和最大值 輸入 42 3 1 23 4 2 25 輸出 7解題思路 對每個物品有兩種選擇,選或者不選。選擇該物品的話,總價值會增加,剩...

C 01揹包問題

有n件物品和乙個容量為v 的揹包。放入第 i 件物品耗費的空間是 c i 得到的價值是 w i 求解將哪些物品裝入揹包可使價值總和最大。這是最基礎的揹包問題,特點是 每種物品僅有一件,可以選擇放或不放。用子問題定義狀態 即 f i,v 表示前i件物品恰放入乙個容量為v的揹包可以獲得的最大價值。則其狀...