1、01揹包問題描述
已知:有 n 件物品和乙個容量為 v 的揹包。第i件物品的重量為w[i],得到的價值是 c[i].
問題:求解將哪些物品裝入揹包可使價值總和最大。
條件:每種物品只有一件,可以選擇放或者不放
2、基本思路
01揹包的特點:每種物品只有一件,可以選擇放或者不放
子問題定義狀態
f[i]
[v]:前i件物品放到乙個容量為v的揹包中的最大價值
狀態轉移方程f[i]
[v]=
max(f[i-1]
[v],f[i-1]
[v-w[i]
]+c[i]
)
分析:
考慮到子問題的狀態定義,將前i件物品都放到容量為v的揹包中,那麼第i件物品有兩種選擇:放&不放;
(1)當選擇第i將物品不放入揹包時,那麼此時只有前i-1件物品放到容量為v的揹包中,所以最大的價值為:f[i-1][v];
(2)當選擇第i間物品放到揹包時,那麼此時前i-1件物品就會放到容量為v-w[i]的揹包中,所以最大的價值為:f[i-1][v-w[i]+c[i]
舉個栗子:
揹包承重量10,5件物品,重量[2,3,3,4,6], 價值[1,2,5,9,4].
**實現
//01揹包
#include
#include
#include
using
namespace std;
intmaxvalue
(int n,
int c, vector<
int> v, vector<
int> w)
}//處理第一行
for(
int j =
0; j <= c; j++
)for
(int i =
1; i < n; i++
)else}}
return dp[n -1]
[c];
}int
main()
效能分析
時間複雜度為:o(nv)
空間複雜度為:o(nv),其中n表示物品的數量,v表示揹包的容量
時間複雜度不能在優化,但是空間複雜度可以繼續優化為o(v)
3、空間複雜度優化
上述方法採用的是二維陣列,可以繼續優化為一維陣列
狀態定義:f[v] :前i件物品放到乙個容量為v的揹包中的最大價值
狀態轉移方程:f[v]=max(f[v],f[v-w[i]]+c[i])
**實現
//01揹包
#include
#include
#include
using
namespace std;
intmaxvalue_1
(int n,
int c, vector<
int> v, vector<
int> w)
}return dp[c];}
intmain()
4、初始化細節問題
在求解揹包問題時,事實上有兩種不太相同的問法。
有的題目要求「恰好裝滿揹包」時的最優解,有的題目則並沒有要求必須把揹包裝滿。
這兩種問法的實現方法是在初始化的時候有所不同。
(1)第一種問法,要求恰好裝滿揹包,那麼在初始化時除了 f[0] 為 0,其它f[1][v] 均設為 -∞ ,這樣就可以保證最終得到的 f[v ] 是一種恰好裝滿揹包的最優解。
(2)如果並沒有要求必須把揹包裝滿,而是只希望**盡量大,初始化時應該將 f[n][v]全部設為 0。
原因:初始化的 f 陣列事實上就是在沒有任何物品可以放入揹包時的合法狀態。如果要求揹包恰好裝滿,那麼此時只有容量為 0 的揹包可以在什麼也不裝且價值為 0 的情況下被「恰好裝滿」,其它容量的揹包均沒有合法的解,屬於未定義的狀態,應該被賦值為 -∞ 了。如果揹包並非必須被裝滿,那麼任何容量的揹包都有乙個合法解「什麼都不裝」,這個解的價值為 0,所以初始時狀態的值也就全部為 0了。
4、小結
01 揹包問題是最基本的揹包問題,它包含了揹包問題中設計狀態、方程的最基本思想。另外,別的型別的揹包問題往往也可以轉換成 01 揹包問題求解。
揹包問題九講筆記 01揹包問題
有 n 件物品和乙個容量為 v的揹包 放入第 i 件物品 放入第 i件物品耗費的容量是ci 所獲得的價值是wi 每件物品只有乙個 求將哪些物品放入揹包可使價值總和最大 一般來說求極值的問題可分為貪心,動態規劃,以及遍歷所有可能 在這三中方法中,動態規劃是最常見的,也是很難想出來的 其中最難的是定義子...
揹包九講之 01揹包
01揹包是最基礎的揹包問題,其中01代表的就是第i個物品的選或不選,在此先設v i 為體積,w i 為價值。很顯然,我們可以使用二位陣列dp i j 來表示前i個物品在揹包容量為j的時候可存放的最大價值。首先dp 0 0 0是很顯然的。而計算dp i j 時,存在01兩種情況 選或不選第i件物品。1...
揹包九講專題 01揹包
樸素2維無優化寫法 includeusing namespace std const int maxn 1e3 5 int dp maxn maxn v maxn w maxn intmain printf d n dp n m view code 優化1維寫法 關於優化是怎麼來的?首先為什麼第二個...