多重背包的二进制优化

#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
using namespace std;int n,m;
int dp[100010];int w[100010],v[100010],num[100010];
void n_pack(int weight,int value)//普通01背包的做法 
{
	for(int i=m;i>=weight;i--)
	 dp[i]=max(dp[i],dp[i-weight]+value);
}
void w_pack(int weight,int value)//完全背包的做法 
{
	for(int i=weight;i<=m;i++)
	dp[i]=max(dp[i],dp[i-weight]+value);
}
int main()
{
	int t;scanf("%d",&t);
	while(t--)
	{memset(dp,0,sizeof(dp)); 
		cin>>m>>n;
		for(int i=1;i<=n;i++)
		scanf("%d%d%d",&w[i],&v[i],&num[i]);
		for(int i=1;i<=n;i++)
		{
			if(w[i]*num[i]>m)//当一个物品的重量和数量乘积大于背包容积的时候相当于完全背包 
			w_pack(w[i],v[i]); 
		else
		{
			int k=1;//(1,2,4....,3=1+2,在k==2时候其实已经 算了3(1+2); 
			if(k<num[i])
			{
				n_pack(k*w[i],k*v[i]);
				num[i]-=k;
				k<<=1;
			}
			n_pack(num[i]*w[i],num[i]*v[i]);
		}
		}
		cout<<dp[m]<<endl;
	}
}

  

原文地址:https://www.cnblogs.com/flyljz/p/11383349.html