有 n 件物品和乙個容量是 v 的揹包。每件物品只能使用一次。
第 i 件物品的體積是 vi,價值是 wi。
求解將哪些物品裝入揹包,可使這些物品的總體積不超過揹包容量,且總價值最大。
輸出最大價值。
輸入格式
第一行兩個整數,n,v,用空格隔開,分別表示物品數量和揹包容積。
接下來有 n 行,每行兩個整數 vi,wi,用空格隔開,分別表示第 i 件物品的體積和價值。
輸出格式
輸出乙個整數,表示最大價值。
資料範圍
001揹包是動態規劃中揹包問題很典型的乙個題,大意為有一些物品和乙個有一定體積的揹包,每個物品都有自己的價值,詢問揹包內物品的最大價值是多少?
列舉每乙個物品,通過對每乙個物品的取捨來推導狀態轉移方程:
我們用3個陣列來表示狀態,w[n]來表示每乙個物品的價值,v[n]表示每個物品的體積,dp【n】【n】,dp【i,j】表示,當前最多拿 i 個物品,體積小於等於 j 時的最大價值是多少。
關於第 i 個物品的取捨問題:
1. 第 i 個物品不要,則當前狀態和 i-1 的狀態相同,則dp[i][j]=dp[i-1][j]。
2. 第 i 個物品要,則當前狀態等於j-v[i]體積下的最大價值+w[i],所以在這種狀態下,dp[i][j]=dp[i-1][j-v[i]]+w[i]。
目的是求最大價值,因此狀態轉移方程:
dp[i][j]=max(dp[i-1][j],dp[i][j-v[i]]+w[i])
普通01揹包**:
#include
#include
#include
using
namespace std;
const
int n =
1e3+50;
int w[n]
,v[n]
,dp[n]
[n];
intmain()
cout<[m]
}
我們發現當前 i 個物品只和 i-1 個物品的狀態有關,所以我們可以把dp陣列從二維優化到一維,dp[n],dp[i]表示在體積 i 的範圍之內的最大價值。我們可以讓二維陣列原地滾動。
一維狀態轉移方程:dp[j]=max(dp[j],dp[j-v[i]]+w[i])
先貼**:
#include
#include
#include
using
namespace std;
const
int n =
1e3+50;
int w[n]
,v[n]
,dp[n]
;int
main()
觀察**發現,和二維不一樣的是,一維的內迴圈是從m->v[i],為什麼呢,因為要實現原地滾動,就要借助上一次修改的值(i-1),但是如果從前往後遍歷的話,會造成一種什麼情況,因為是一維陣列,所以上一次修改的值在這一次開始操作的時候已經被覆蓋了,導致後面的 j 在做狀態轉移方程時,使用的是當前行的值而不是 i-1 行,導致結果不准,所以我們從後往前遍歷,先改後面再改前面,保證每乙個j 都使用的 i - 1 行的值,再結合狀態轉移方程,最後dp[m]即為要求的值,意為在m體積範圍內可以帶走的最大價值。 DP 揹包九講之01揹包
有n件物品和乙個容量為v 的揹包。放入第i件物品耗費的空間是ci,得到 的價值是wi。求解將哪些物品裝入揹包可使價值總和最大。這是最基礎的揹包問題,特點是 每種物品僅有一件,可以選擇放或不 放。用子問題定義狀態 即f i,v 表示前i件物品恰放入乙個容量為v的揹包可以 獲得的最大價值。則其狀態轉移方...
DP 揹包九講之01揹包
有 n 件物品和乙個容量是 v 的揹包。每件物品只能使用一次。第 i 件物品的體積是 vi,價值是 wi。求解將哪些物品裝入揹包,可使這些物品的總體積不超過揹包容量,且總價值最大。輸出最大價值。輸入格式 第一行兩個整數,n,v,用空格隔開,分別表示物品數量和揹包容積。接下來有 n 行,每行兩個整數 ...
揹包九講之 01揹包
01揹包是最基礎的揹包問題,其中01代表的就是第i個物品的選或不選,在此先設v i 為體積,w i 為價值。很顯然,我們可以使用二位陣列dp i j 來表示前i個物品在揹包容量為j的時候可存放的最大價值。首先dp 0 0 0是很顯然的。而計算dp i j 時,存在01兩種情況 選或不選第i件物品。1...