您的位置:首页 > 其它

【51Nod 1086】背包问题 V2

2016-10-24 20:29 309 查看

Description

有N种物品,每种物品的数量为C1,C2……Cn。从中任选若干件放在容量为W的背包里,每种物品的体积为W1,W2……Wn(Wi为整数),与之相对应的价值为P1,P2……Pn(Pi为整数)。求背包能够容纳的最大价值。

Solution

这是一个经典的有限背包问题,但是它需要优化复杂度。

他用到了一个很奇妙也很机智的思想:每个数可以用二进制来表示。

二进制优化

因为每个数的个数如果逐个枚举的话,那么会有很多冗余的状态。

每个数可以拆成:1+2+4+…+(m-sum)

每次直接用上面的数字的个数来转移就好了。

为什么可以这样呢?因为一个数可以表示为二进制,那么就是说可以有好多个二的次幂加起来。

时间复杂度优化到O(nmlog(m))

Code

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define fo(i,a,b) for(i=a;i<=b;i++)
#define fod(i,a,b) for(i=a;i>=b;i--)
using namespace std;
typedef long long ll;
const int maxn=107,mxx=50007;
ll i,j,k,l,t,n,m,ans;
ll w,p,c,f[mxx];
int main(){
scanf("%d%d",&n,&m);
fo(i,1,n){
scanf("%lld%lld%lld",&w,&p,&c);
for(j=1;j<=c;c-=j,j*=2){
fod(k,m,j*w){
f[k]=max(f[k],f[k-j*w]+j*p);
}
}
if(!c)continue;
fod(k,m,c*w){
f[k]=max(f[k],f[k-c*w]+c*p);
}
}
fod(i,m,0)ans=max(ans,f[i]);
printf("%lld\n",ans);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: