codevs 3269 混合背包

Posted on 2016-01-08 19:34  ziliuziliu  阅读(109)  评论(0编辑  收藏  举报

分类讨论~~~~~二进制一定要分出1来。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
using namespace std;
long long f[205005],n,v;
long long w[505],p[505],num[505];
void work1(long long x)
{
for (long long i=w[x];i<=v;i++)
f[i]=max(f[i],f[i-w[x]]+p[x]);
}
void work2(long long x)
{
for (long long i=v;i>=w[x];i--)
f[i]=max(f[i],f[i-w[x]]+p[x]);
}
void work3(long long x,long long numm)
{
long long k=1,w1[255],p1[255],cnt=0;
for (;;)
{
if (k>numm) break;
cnt++;
w1[cnt]=w[x]*k;
p1[cnt]=p[x]*k;
numm=numm-k;
k=k<<1;
}
if (numm>0)
{
cnt++;
w1[cnt]=w[x]*numm;
p1[cnt]=p[x]*numm;
}
for (long long i=1;i<=cnt;i++)
for (long long j=v;j>=w1[i];j--)
f[j]=max(f[j],f[j-w1[i]]+p1[i]);
}
int main()
{
memset(f,0,sizeof(f));
scanf("%lld%lld",&n,&v);
for (long long i=1;i<=n;i++)
scanf("%lld%lld%lld",&w[i],&p[i],&num[i]);
for (long long i=1;i<=n;i++)
{
if (num[i]==-1)
work1(i);
else
work3(i,num[i]);
}
printf("%lld\n",f[v]);
return 0;
}