第三講 多重背包問題


有 N 種物品和一個容量是 VV 的背包。

第 i 種物品最多有 si 件,每件體積是 vi,價值是 wi

求解將哪些物品裝入背包,可使物品體積總和不超過背包容量,且價值總和最大。
輸出最大價值。

輸入格式

第一行兩個整數N,V,用空格隔開,分別表示物品種數和背包容積。

接下來有 N行,每行三個整數vi,wi,si,用空格隔開,分別表示第 i 種物品的體積、價值和數量。

輸出格式

輸出一個整數,表示最大價值。

數據范圍

0<N≤1000
0<V≤2000
0<vi,wi,si≤2000

提示:

本題考查多重背包的二進制優化方法。

輸入樣例

4 5
1 2 3
2 4 1
3 4 3
4 5 2

輸出樣例:

10

 

狀態計算
集合划分

第i個物品最多選多少個
f[i,j] = max(f[i-1,j-kv]+kw) k=0,1,2,…,s[i]

二進制優化
f[i,j] = Max(f[i-1,j], f[i-1,j-v]+w,f[i-1,j-2v]+2w,…,f[i-1,j-sv]+sw)
f[i,j-v]=Max(f[i-1,j-v], f[i-1,j-2v]+w,…, f[i-1,j-(s+1)v]+(s+1)w)

二進制的優化方式
s=1023

1,2,4,8,…,512

0~1023

把多種背包某個物品有s次,轉化為logS的物品的01背包問題,因此可以拼湊出問題的解

注意這里的湊數,最后一個是剩余的解
如 s=200
1,2,4,8,16,32,64,73

1~127
73~200
所以只湊出了0-200的解

s
1,2,4,8,..,2^k,c
c=s-(2^{k+1}-1)

c<2^{k+1}
s<=2^{k+2}-1;

優化步驟
總物品數:NlogS
時間:VNlogS

 1 #include <iostream>
 2 #include <algorithm>
 3 using namespace std;
 4 
 5 //N*log(s)*V 
 6 const int N = 11000;//N*log(s)向上取整
 7 //總物品數:NlogS
 8 
 9 int n,m;
10 int w[N];//重量
11 int v[N];//價值
12 int f[N];//[j], j重量的最大價值
13 
14 int main()
15 {
16     cin >> n >> m;
17     
18     int cnt = 0;
19     for(int i = 1;i <= n;i ++)
20     {
21         int a,b,s;
22         cin >> a >> b >> s;
23         int k = 1;
24         while(k <= s)
25         {
26             cnt++;
27             w[cnt] = a * k;
28             v[cnt] = b * k;
29             s -= k;
30             k *= 2;
31         }
32         
33         if(s > 0)
34         {
35             cnt++;
36             w[cnt] = a * s;
37             v[cnt] = b * s;
38         }
39     }
40     n = cnt;
41     for(int i = 1;i <= n;i ++)
42         for(int j = m;j >= w[i];j --)
43             f[j] = max(f[j],f[j - w[i]] + v[i]);
44 
45             
46     cout << f[m] << endl;
47 
48     return 0;
49 }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM