有n
nn種物品和乙個容量是v
vv的揹包。第i
ii種物品最多有s
is_i
si件,每件體積是v
iv_i
vi,價值是w
iw_i
wi。求解將哪些物品裝入揹包,可使物品體積總和不超過揹包容量,且價值總和最大。輸出最大價值。
輸入格式:
第一行兩個整數,n
nn,v
vv,用空格隔開,分別表示物品種數和揹包容積。接下來有n
nn行,每行三個整數vi,
wi,s
iv_i,w_i,s_i
vi,wi
,si
,用空格隔開,分別表示第i
ii種物品的體積、價值和數量。
輸出格式:
輸出乙個整數,表示最大價值。
資料範圍:
0
1000
0< n\le 1000
01000
0
2000
0< v\le 2000
02000
0
,wi,
si
≤2000
00,wi
,si
≤20
00思路是動態規劃。但這裡需要用二進位制優化,其基本思路是,將每個物品的個數s
ss拆成若干個形如2
k2^k
2k的個數的」打包」,這樣就將多重揹包問題轉為了0−1
0-10−
1揹包問題了,從而將時間複雜度降為o(v
∑i=1
nlogs
i)
o(v\sum_^ \log s_i)
o(v∑i=
1nlogsi
)。例如,如果乙個物品有10
1010
個,那麼可以將它拆成1+2
+22+
31+2+2^2+3
1+2+22
+3,這樣這個物品的所有取法,一定包含於將其拆成若干小塊,每個小塊最多取乙個的取法。其正確性證明參考**如下:
時間複雜度o((#include
using
namespace std;
const
int n =
25000
, m =
2010
;int n, m;
int v[n]
, w[n]
;int f[n]
;int
main()
// 如果沒拆乾淨,把剩餘的部分也打包
if(s >0)
}// 拆完後新的個數重新賦值,然後做0-1揹包
n = cnt;
for(
int i =
1; i <= n; i++
)for
(int j = m; j >=
0; j--)if
(j >= v[i]
) f[j]
=max
(f[j]
, f[j - v[i]
]+ w[i]);
cout << f[m]
<< endl;
return0;
}
∑i=1
nlogs
i)v)
o((\sum_^ \log s_i) v)
o((∑i=
1nlogsi
)v)
,空間o(v
)o(v)
o(v)
。**裡n
nn開25000
25000
2500
0是1000
×log
2000
1000\times \log 2000
1000
×log20
00算出來的。
AcWing 5 多重揹包問題 II
題目描述 有 n 種物品和乙個容量是 v的揹包。第 i種物品最多有 si 件,每件體積是 vi,價值是 wi。求解將哪些物品裝入揹包,可使物品體積總和不超過揹包容量,且價值總和最大。輸出最大價值。輸入格式 第一行兩個整數,n,v,用空格隔開,分別表示物品種數和揹包容積。接下來有 n行,每行三個整數 ...
acwing 5 多重揹包問題 II
有 n 種物品和乙個容量是 v 的揹包。第 i 種物品最多有 si 件,每件體積是 vi,價值是 wi。求解將哪些物品裝入揹包,可使物品體積總和不超過揹包容量,且價值總和最大。輸出最大價值。輸入格式 第一行兩個整數,n,v,用空格隔開,分別表示物品種數和揹包容積。接下來有 n 行,每行三個整數 vi...
多重揹包問題 II
有 n 種物品和乙個容量是 v 的揹包。第 i 種物品最多有 si 件,每件體積是 vi,價值是 wi。求解將哪些物品裝入揹包,可使物品體積總和不超過揹包容量,且價值總和最大。輸出最大價值。輸入格式 第一行兩個整數,n,v,用空格隔開,分別表示物品種數和揹包容積。接下來有 n 行,每行三個整數 vi...