[学习笔记]二进制优化多重背包

算法

我们知道在原本的多重背包中
我们会将一个大小为\(k\)的物品 拆成\(k\)个大小为\(1\)的物品来进行\(01背包\)
但我们发现这样处理一个物品时间复杂度将变为\(O(kv)\)
这个复杂度在某些题目中是不能接受的
所以我们从拆分角度优化
我们考虑二进制优化拆分
这里有我的另外一篇博客 关于二进制拆分的(我博客园开篇之作 感觉写的不好)
使用二进制拆分的处理一个物品时间复杂度将变为\(O(vlogk)\)
所以这里仅给出代码

	scanf("%d%d",&n,&v);
	ll k = n;
	for(int i = 1;i <= n;i++)
	scanf("%d%d%d",&a[i],&b[i],&c[i]);
	for(int i = 1;i <= n;i++){
		for(int j = 1;j <= c[i];(j = j << 1)){
		c[i] -= j;
		a[++k] = a[i] * j;
		b[k] = b[i] * j;
	}
	    if(c[i]){
	    	a[++k] = c[i] * a[i];
	    	b[k] = c[i] * b[i];
		}
	}
	for(int i = n + 1;i <= k;i++)
	for(int j = v;j >= b[i];j--)
	dp[j] = max(dp[j],dp[j - b[i]] + a[i]),ans = max(ans,dp[j]);
	cout<<ans<<endl;
	return 0;
posted @ 2020-10-22 15:19  fhq_treap  阅读(132)  评论(0编辑  收藏  举报