51nod 多重背包 [二进制优化]

问题描述

一个背包,承量有限为W,有n种物体,第i种物体,价值Vi,占用重量为 Wi,且有Ci件,选择物品若干放入背包,使得总重量不超过背包的承重。总价值最大?

思路:

把C物品分开来对待,就成了01背包问题。但是如果C的数量特别大的时候这样做的效率显然不够。可以用二进制优化下。
例如一个物品有10个,可以把10拆成1, 2 ,4, 3,这几个数的组合可以是10内的任何数,显然和一个一个的对待等价。
#include "bits/stdc++.h"
using namespace std;
const int maxn = 50000 + 10;
int sz[maxn], val[maxn];
int dp[maxn];
int main(int argc, char const *argv[]) {
int N, W;
scanf("%d%d", &N, &W);
int cnt = 0;
int w, p, c;
for (int i = 0; i < N; i++) {
scanf("%d%d%d", &w, &p, &c);
for (int k=1; k<=c; k<<=1) {
val[cnt] = k*p;
sz[cnt++] = k*w;
c -= k;
}
if (c > 0) val[cnt] = c*p, sz[cnt++] = c*w;
}
for (int i = 0; i < cnt; i++) {
for (int j = W; j >= sz[i]; j--) {
dp[j] = max(dp[j], dp[j - sz[i]]+val[i]);
}
}
printf("%d\n", dp[W]);
return 0;
}

转载于:https://www.cnblogs.com/cniwoq/p/7340243.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值