問題描述:有n個物品,第i個物品的重量與價值分別為 w[i
]w[i]
w[i]
與 v[i]
v[i]
v[i]
且第i種物品最多有p[i]件。揹包容量為v,試問在每個物品不超過其上限的件數(物品必須保持完整)的情況下,如何讓揹包裝入的物品具有更大的價值總和。現有資料如下:
w =[2
,3,4
,5];
v =[3,
4,5,
6];p =[1
,1,1
,1];
// 結果與0-1揹包一樣。
v =8
;
解題思路:令 dp[
i][j
]dp[i][j]
dp[i][
j]表示從編號1~i的物品中挑選任意數量的任意物品放入容量為j的揹包中得到的最大價值,那麼有 dp[
i][j
]=ma
xdp[i][j]=max\
dp[i][
j]=m
ax。
public
intknapsackproblem
(int
w,int[
] v,
int[
] p,
int cap)}}
return dp[w.length]
[cap]
;}
時間複雜度為 o(n
v∑p[
i]
)o(nv \sum p[i])
o(nv∑p
[i])
,略高。
時間優化:將該問題轉換為0-1揹包問題,即若第i種物品有s件,那麼可以將其分成s份」不同「的物品。但是略複雜。
二進位制優化法:若要表示1~s之內的任意乙個數字,只需要 log
2(s)
log_2(s)
log2(
s)向上取整個數即可完全表示,分別取 1,2
,4,⋯
,2lo
g2(x
)1,2,4,\cdots, 2^(x)}
1,2,4,
⋯,2l
og2
(x) 個數,若最有乙個數不足 2lo
g2(x
)2^(x)}
2log2
(x),則取 s−1
−2−4
−⋯
s-1-2-4-\cdots
s−1−2−
4−⋯。即十進位制數10可以用4個數表示,分別是1,2,4,3。前三個數最大能表示的數是7。故剩下乙個數取10-7=3。此時原問題就轉換為0-1揹包問題了。
public
intknapsackproblem
(int
w,int[
] v,
int[
] p,
int cap)}if
(s >0)
}}return dp[cap]
;}
時間複雜度為 o(n
v∑lo
g2(p
[i])
)o(nv\sum log_(p[i]))
o(nv∑l
og2
(p[i
]))。
揹包問題之多重揹包
相比完全揹包問題,多重揹包指定物品個數。我們可以將多重揹包問題轉化為0 1揹包 容易超時,優化後續補充 進行處理。求最好價值問題的多重揹包不能使用記錄使用物品次數的方式進行簡化 題目給定一些不同價值的硬幣,求這些硬幣可以組成1 n範圍內值的數量。public int backpack int n,i...
揹包問題之多重揹包
其實感覺多重揹包比01揹包和完全揹包都要難,每件物品的數量可能不止一件,還是求放入揹包的物品的最大價值。在揹包九講中,給出的動態轉移方程為 f i v max 但是感覺還是考慮邊界問題比較煩人,所以我想的是把多重揹包和之前的01揹包聯絡起來.不知道行不行 這裡我寫了一種一維dp陣列的寫法,在這題測試...
揹包問題 多重揹包
有n種物品和乙個容量為w的揹包。第i種物品最多有n i 件可用,每件重量是w i 價值是v i 求解將哪些物品裝入揹包可使這些物品的重量總和不超過揹包容量,且價值總和最大。1.使用三重迴圈進行遞推 狀態轉移式為 dp i j max 關鍵 如下 void solve printf d n dp n ...