1086 背包问题 V2
- 1.0 秒
- 131,072.0 KB
- 20 分
- 3级题
有N种物品,每种物品的数量为C1,C2......Cn。从中任选若干件放在容量为W的背包里,每种物品的体积为W1,W2......Wn(Wi为整数),与之相对应的价值为P1,P2......Pn(Pi为整数)。求背包能够容纳的最大价值。
收起
输入
第1行,2个整数,N和W中间用空格隔开。N为物品的种类,W为背包的容量。(1 <= N <= 100,1 <= W <= 50000) 第2 - N + 1行,每行3个整数,Wi,Pi和Ci分别是物品体积、价值和数量。(1 <= Wi, Pi <= 10000, 1 <= Ci <= 200)
输出
输出可以容纳的最大价值。
输入样例
3 6 2 2 5 3 3 8 1 4 1
输出样例
9
题解:好久没做背包题了,回忆一下,多重背包模板题;
#include<stdio.h>
#include<queue>
#include<string.h>
#include<algorithm>
#include<set>
#include<map>
#include<math.h>
#include<stack>
#include<vector>
#include<bitset>
#include<iostream>
#define ullmax 1844674407370955161
#define llmax 9223372036854775807
#define intmax 2147483647
#define re register
#define pushup() tree[rt]=max(tree[rt<<1],tree[rt<<1|1])
using namespace std;
typedef long long ll;
const int N=1e5+5;
int n;
ll dp[N],M; // M 所求最大价值
struct node{
ll x,y,z;
}f[105];
void one(ll w,ll v){ // 0-1背包
for(ll i=M;i>=w;i--) dp[i]=max(dp[i],dp[i-w]+v);
}
void two(ll w,ll v){ // 完全背包
for(ll i=w;i<=M;i++) dp[i]=max(dp[i],dp[i-w]+v);
}
void work(ll w,ll v,ll num){ // w : 重量(体积) v : 价值 num : 数量
if(w*num>=M){ // 如果该物体总体积就达到最大容量,可以用完全背包
two(w,v);
return ;
}
ll k=1;
while(k<num){ // 二进制优化
one(k*w,k*v);
num-=k;
k<<=1;
}
if(num) one(num*w,num*v);
}
int main(){
scanf("%d %lld",&n,&M);
for(int i=0;i<n;i++)
scanf("%lld %lld %lld",&f[i].x,&f[i].y,&f[i].z);
for(int i=0;i<n;i++)
work(f[i].x,f[i].y,f[i].z);
printf("%lld\n",dp[M]);
return 0;
}