背包DP——多重背包
多重背包也是 0-1 背包的一个变式。与 0-1 背包的区别在于每种物品有 k 个,而非一个。
朴素
直接把相同的每个物品视作各个单独的物品,没有关联,仅条件相同;
转换后直接用01背包的状态转移方程
注意:在大数据下容易爆空间时间
二进制分组优化
与朴素相比,优化利用二进制原理(任意数可以由多个不同 2^j 数的和表示)
把每种物品的数量k分成多个2j,如1,2,4,8,16……;若k非2i,最后剩下的单独成一组
举几个例子
优化后就可以直接用01背包解决
例题
https://www.luogu.com.cn/problem/P1776
宝物筛选
题目描述
终于,破解了千年的难题。小 FF 找到了王室的宝物室,里面堆满了无数价值连城的宝物。
这下小 FF 可发财了,嘎嘎。但是这里的宝物实在是太多了,小 FF 的采集车似乎装不下那么多宝物。看来小 FF 只能含泪舍弃其中的一部分宝物了。
小 FF 对洞穴里的宝物进行了整理,他发现每样宝物都有一件或者多件。他粗略估算了下每样宝物的价值,之后开始了宝物筛选工作:小 FF 有一个最大载重为
输入格式
第一行为一个整数
接下来
输出格式
输出仅一个整数,表示在采集车不超载的情况下收集的宝物的最大价值。
样例 #1
样例输入 #1
4 20
3 9 3
5 9 1
9 4 2
8 1 3
样例输出 #1
47
提示
对于
对于
Code
点击查看代码
const int maxn = 1e7 + 10;
int dp[maxn], w[maxn], v[maxn], sum[maxn];
int wnew[maxn], vnew[maxn];
void solve() {
int n, m;
cin >> n >> m;
int cnt = 0;
for (int i = 1; i <= n; i++) {
cin >> w[i] >> v[i] >> sum[i];
int x = sum[i], j = 1;
while (x) {
if (j <= x) {
x -= j;
wnew[++cnt] = w[i] * j;
vnew[cnt] = v[i] * j;
j <<= 1;
}
else {
wnew[++cnt] = w[i] * x;
vnew[cnt] = v[i] * x;
break;
}
}
}
for (int i = 1; i <= cnt; i++) {
for (int j = m; j >= wnew[i]; j--) {
dp[j] = max(dp[j], dp[j - wnew[i]] + vnew[i]);
}
}
cout << dp[m];
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· winform 绘制太阳,地球,月球 运作规律
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人