多重背包问题(二进制优化)

多重背包问题

有 N 种物品和一个容量是 V 的背包。

第 i 种物品最多有 si 件,每件体积是 vi,价值是 wi。

求解将哪些物品装入背包,可使物品体积总和不超过背包容量,且价值总和最大。
输出最大价值。

输入格式
第一行两个整数,N,V,用空格隔开,分别表示物品种数和背包容积。

接下来有 N 行,每行三个整数 vi,wi,si,用空格隔开,分别表示第 i 种物品的体积、价值和数量。

输出格式
输出一个整数,表示最大价值。

数据范围
0<N≤1000
0<V≤2000
0<vi,wi,si≤2000
提示:
本题考查多重背包的二进制优化方法。

输入样例
4 5
1 2 3
2 4 1
3 4 3
4 5 2
输出样例:
10
观察发现这个数据远远大于一般的多重背包问题
所以机智的我就出现了二进制优化!!!
先看代码
就是把多重背包转换为01背包

#include<stdio.h>
#include<math.h>
#include<algorithm>
using namespace std;
int n,m,s[10000],vv[10000],v[100000],ww[100000],w[100000],i,j,k,t,d[10000000];
int main()
{
    
    

	scanf("%d%d",&n,&m);
	for(i=1;i<=n;i++)
	scanf("%d%d%d",&vv[i],&ww[i],&s[i]);
	for(i=0;i<=m;i++)
	d[i]=0;
	k=1;
	for(i=1;i<=n;i++)
	{
    
    
		for(j=1;j<s[i];j*=2)//二进制优化过程
		{
    
    
			v[k]=j*vv[i],w[k]=j*ww[i];
			k++;
			s[i]-=j;
		}
		if(s[i])
		{
    
    
			v[k]=s[i]*vv[i],w[k]=s[i]*ww[i];
			k++;
		}

	}
 k=k-1;//多算的1
 //这个是看看优化后的
	//for(i=1;i<=k;i++)
	//printf("%d %d\n",v[i],w[i]);
	//01背包他又来了
	for(i=1;i<=k;i++)
	for(j=m;j>=v[i];j--)
	{
    
    
		d[j]=max(d[j],d[j-v[i]]+w[i]);
	}
	printf("%d\n",d[m]);
}

为什么要用二进制??
自己悟!

猜你喜欢

转载自blog.csdn.net/m0_46381590/article/details/111479870