ACWing 5 多重揹包問題 II

2021-10-19 12:25:58 字數 2005 閱讀 4289

有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

nlog⁡s

i)

o(v\sum_^ \log s_i)

o(v∑i=

1n​logsi

​)。例如,如果乙個物品有10

1010

個,那麼可以將它拆成1+2

+22+

31+2+2^2+3

1+2+22

+3,這樣這個物品的所有取法,一定包含於將其拆成若干小塊,每個小塊最多取乙個的取法。其正確性證明參考**如下:

#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;

}

時間複雜度o((

∑i=1

nlog⁡s

i)v)

o((\sum_^ \log s_i) v)

o((∑i=

1n​logsi

​)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...