AcWing 5. 多重背包问题 II

题面:
N 件物品和一个容量是 V 的背包。
i 件物品最多有 si,每件体积是 vi,价值是 wi
求解将哪些物品装入背包,可使这些物品的体积总和不超过背包容量,且价值总和最大
输出最大价值。

原题链接:5. 多重背包问题 II - AcWing

先前的思路:将 s 个物品分成 s

由此转换为 s 个 01背包问题,例如 7 就可以拆解为 1 1 1 1 1 1 1

二进制优化思路:将 s 个物品分成 log(s)

20+21+22=1+2+4=7
实际上,就像每一个小于等于 7 的数都可以通过 1 2 4 这三个数字组合出来一样,
最少需要 ceil(log2s) 个数,就可以组合出 0s 之间的所有数。

对于 s 不属于 2n1 的情况,将 si=0[log2s]2i 作为第 ceil(log2s) 个数即可。
例如,对于 10,就可以拆解为1 2 4 3。既然每一个 07 之间的数都可以通过 1 2 4 组合出来,那么它们加上 3 就可以表示 010 之间的数。

时间复杂度:O(n3)O(n2logn)

#include <bits/stdc++.h>
using namespace std;
const int N = 2010;
int n, m, f[N];
struct good {
int v, w;
};
int main()
{
vector<good> goods;
cin >> n >> m;
//拆堆
for (int i = 0; i < n; i++) {
int v, w, s;
cin >> v >> w >> s;
for (int j = 1; j <= s; j *= 2) {
s -= j;
goods.push_back({ v * j, w * j });
}
if (s > 0) goods.push_back({ v * s, w * s });
}
//01板子
for (auto g : goods)
for (int j = m; j >= g.v; j--)
f[j] = max(f[j], f[j - g.v] + g.w);
cout << f[m];
}

  1. https://www.acwing.com/activity/content/code/content/7361624/) ↩︎

posted @   蒟蒻爬行中  阅读(7)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 上周热点回顾(2.24-3.2)
点击右上角即可分享
微信分享提示