比較詳細的講01揹包問題(值得看)

2021-08-07 23:21:44 字數 2475 閱讀 6825

面試筆試經常碰到01揹包問題,頭疼。這裡來詳細講解下;

01揹包問題:乙個揹包總容量為v,現在有n個物品,第i個物品體積為weight[i],價值為value[i],現在往揹包裡面裝東西,怎麼實現物品價值最大?

看到這個問題,可能會想到貪心演算法;但是貪心演算法其實是不對,例如最少硬幣找零問題,要用動態規劃。動態規劃思想就是解決子問題並記錄子問題的解,這樣就不用重複解決子問題了。

動態規劃先找出子問題,我們可以這樣考慮:在物品比較少,揹包容量比較小的時候怎麼解決;用乙個陣列f[i][j]表示在額放進只有i個物品,容量為j的情況下揹包問題的最優解,那麼當物品種類變大為i+1時,最優解是什麼?第i+1物品可以選擇放進揹包或者不放進揹包(這就是0和1);假設放進揹包(前提是放的下),那麼f[i+i][j]=f[i][j-weight[i+1]]+value[i+1];

如果不放進揹包,那麼f[i+1][j]=f[i][j]

這就得出了狀態轉移方程;

f[i+1][j]=max(f[i][j], f[i][j-weight[i]]+value[i+1]);

**實現:

#includeusing namespace std;  

#define v 1500

unsigned int f[10][v];//全域性變數,自動初始化為0

unsigned int weight[10];

unsigned int value[10];

#define max(x,y) (x)>(y)?(x):(y)

int main()

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

for (int j=1; j<=m; j++)

else

f[i][j]=f[i-1][j];

} cout<

可以進一步優化記憶體的使用,上面計算f[i][j]可以看出,在計算f[i][j]時只使用了f[i-1][0....i]沒有使用其他子問題,因此儲存子問題的解時,只儲存[i-1]子問題的解即可,這樣可以用兩個一維陣列解決,乙個儲存子問題,乙個儲存子問題正在解決的子問題

在進一步思考,計算f[i][j]只使用了f[i-1][0....j],沒有使用f[i-1][j+1]這樣的話,我們先計算j的迴圈時,讓j=m.....1,只使用乙個一維陣列即可。

for i=1...n

for j=m....1

f[j]=max(f[j], f[j-weight[i]+value[i]]);

#includeusing namespace std;

#define v 1500

unsigned int f[v];//全域性變數,自動初始化為0

unsigned int weight[10];

unsigned int value[10];

#define max(x,y) (x)>(y)?(x):(y)

int main()

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

for (int j = m; j >= 1; j--)

}cout << f[m] << endl;//輸出最優解

}

在看完01揹包問題,再來看完全揹包問題;乙個揹包總容量為v,現在有n個物品,第i個物品體積為weight[i],價值為value[i],每個物品都有無限多件,現在往揹包裡裝東西,怎麼裝能使揹包內的物品價值最大;

對比一下,看到的去唄是,完全揹包問題中,物品有無限多件,往揹包裡新增物品時,只要當前揹包沒裝滿,可以一直新增,那麼狀態轉移方程為:

f[i+1][j]=max(f[i][j-k*weight[i+1]]+value[i+1]*k),其中0<=k=v/weight[i+1];

使用記憶體為一維陣列的偽**:

for i=1....n

for j=1....m

f[j]=max(f[j], f[j-weight[i]+value[i]])

和01揹包問題唯一不同的是j是從1到m,01揹包問題是在前乙個子問題(i-1種物品)的基礎上來解決當前問題的,向i-1種物品時揹包新增第i種物品;而完全揹包問題是在解決當前問題,向i中物品時的揹包新增第i種物品

#includeusing namespace std;

#define v 1500

unsigned int f[v];//全域性變數,自動初始化為0

unsigned int weight[10];

unsigned int value[10];

#define max(x,y) (x)>(y)?(x):(y)

int main()

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

for (int j = 1; j <= m; j++)

}cout << f[m] << endl;//輸出最優解

}

揹包九講 01揹包問題

1 01揹包問題描述 已知 有 n 件物品和乙個容量為 v 的揹包。第i件物品的重量為w i 得到的價值是 c i 問題 求解將哪些物品裝入揹包可使價值總和最大。條件 每種物品只有一件,可以選擇放或者不放 2 基本思路 01揹包的特點 每種物品只有一件,可以選擇放或者不放 子問題定義狀態f i v ...

揹包問題九講筆記 01揹包問題

有 n 件物品和乙個容量為 v的揹包 放入第 i 件物品 放入第 i件物品耗費的容量是ci 所獲得的價值是wi 每件物品只有乙個 求將哪些物品放入揹包可使價值總和最大 一般來說求極值的問題可分為貪心,動態規劃,以及遍歷所有可能 在這三中方法中,動態規劃是最常見的,也是很難想出來的 其中最難的是定義子...

從「採藥」問題看0 1揹包

0 1揹包題目 對於每一件物品,只能取一次,而且有容量限制,每件物品有重量和價值,決策為取與不取 講完了數塔問題,咱們再來看看乙個炒雞老炒雞老的題目 noip2005 pj組 第三題 採藥 題目描述 對於這道題目,我們先來想想搜尋怎麼寫 因為dp和記搜很相似 我們先定義f i j 表示剩餘i時間,取...