第三讲 多重背包问题


有 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