链接:https://www.acwing.com/problem/content/5/
有 N种物品和一个容量是 V 的背包。
第 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
解题思路:把多重背包变成01背包
二进制优化:如果说把其物品都分成一分的话,会超时,
所以其子问题就是:一个数n,最少要多少个数才能把从1-n中的所有数表示出来;
答案是:log2(n)上取整个数
如:7的 1 2 4(2^0 2^1 2^2)
上面7是个特殊的例子:
再如10:如果用 1 2 4 8 表示的话会超过10
所以用1 2 4 3(10-1-2-4)
AC代码:
#include<bits/stdc++.h> using namespace std; typedef long long ll; const int N = 20110; int v[N],w[N],s[N]; int dp[N]; int main() { int n,m,v1,w1,s,cut=0; cin>>n>>m; for(int i=1;i<=n;i++){ cin>>v1>>w1>>s; int k=1; while(k<=s){ cut++; v[cut]=v1*k; w[cut]=w1*k; s-=k; k*=2; } if(s>0){ cut++; v[cut]=v1*s; w[cut]=w1*s; } } n=cut; for(int i=1;i<=n;i++){ for(int j=m;j>=v[i];j--){ dp[j]=max(dp[j],dp[j-v[i]]+w[i]); } } printf("%d",dp[m]); }