题目:
http://codevs.cn/problem/3269/
复杂度O(V*∑logn);
第31行必须再更新一次,因为m并没有拆完;
如2拆为1,但仍然有个1没有用;
又如8拆为1,2,4,但仍然有一个1没有用;
将m进行二进制拆分
分为1,2,4,2^(k-1)和n-2^k+1,且k是满足n-2^k+1>0的最大整数;(百度百科);
因为所有的数都可以用二进制来表示,所以 所有的物品都可以拆成二进制数;
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cstdio>
using namespace std;
const int MAXN=300001;
int dp[MAXN];
int n,V;
int v,w,m;
void solve()
{
scanf("%d%d",&n,&V);
for(int i=1;i<=n;i++)
{
scanf("%d%d%d",&w,&v,&m);
if(m==1) for(int j=V;j>=w;j--) dp[j]=max(dp[j-w]+v,dp[j]);
else if(m==-1)
for(int j=w;j<=V;j++) dp[j]=max(dp[j-w]+v,dp[j]);
else
{
int d=1;
while(m>d)//拆
{
for(int j=V;j>=w*d;j--)
dp[j]=max(dp[j-w*d]+v*d,dp[j]);
m-=d,d*=2;
// cout<<m<<" "<<d<<endl;
}
for(int j=V;j>=w*m;j--) dp[j]=max(dp[j-m*w]+m*v,dp[j]);//不要忘记
}
}
cout<<dp[V];
return;
}
int main()
{
solve();
return 0;
}