[学习笔记]二进制优化多重背包
算法
我们知道在原本的多重背包中
我们会将一个大小为\(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;