DP 复习
背包#
约定使用
01 背包#
每种物品仅有一件,可以选择放或不放。
设
若放第
如果不放第
可以用滚动数组优化掉第一维,但注意要逆序枚举容量以达到“每种物品只能取一件”的限制。
for (int i = 1; i <= n; ++ i) {
for (int j = m; j >= v[i]; -- j) {
f[j] = max(f[j], f[j - v[i]] + w[i];
}
}
若要求 恰好装满,则应将
完全背包#
与 01 背包相似,但每种物品有无限件。
可以用滚动数组优化掉第一维,但注意要 顺序 枚举容量以达到“每种物品可以取无限件”的限制。
完全背包的特点是每种物品可选无限件,所以在考虑“加选一件第
for (int i = 1; i <= n; ++ i) {
for (int j = v[i]; j <= m; ++ j) {
f[j] = max(f[j], f[j - v[i]] + w[i];
}
}
多重背包#
与 01 背包相似,但每种物品最多取
二进制拆分每个物品后跑 01 背包即可。
for (int i = 1; i <= n; ++ i)
{
cin >> a >> b >> m;
for (int j = 1; m - j >= 0; j <<= 1) //二进制拆分优化
{
++ cnt;
v[cnt] = a * j;
w[cnt] = b * j;
m -= j;
}
if (m)
{
++ cnt;
v[cnt] = a * m;
w[cnt] = b * m;
}
}
混合背包#
有的物品只有一个,有的物品有无限个,还有的物品有有限个。
缝合怪,把前三种代码缝合起来即可。
二维费用背包#
对于每件物品,具有两种不同的费用,选择这件物品必须同时付出这两种费用。对于每种费用都有一个可付出的最大值(背包容量)。问怎样选择物品可以得到最大的价值。
设第
费用加了一维,只需状态也加一维即可。设
仍然可以滚动数组,按照背包类型确定枚举顺序即可。
有时,“二维费用”的条件是以“最多只能取 U 件物品” 来给出的。这事实上相当于每件物品多了一种“件数”的费用,每个物品的件数费用均为 1,可以付出的最大件数费用为 U。
另一种看待二维背包问题的思路是:将它看待成复整数域上的背包问题。也就是说,背包的容量以及每件物品的费用都是一个复整数。而常见的一维背包问题则是自然数域上的背包问题。所以说,一维背包的种种思想方法,往往可以应用于二位背包问题的求解中,因为只是数域扩大了而已。
分组背包#
有
这个问题变成了每组物品有若干种策略:是选择本组的某一件,还是一件都不选。
设
其中
for (int i = 1; i <= K; ++ i)
for (int j = V; j >= 0; -- j)
for (int k : group[i])
// 遍历组 i 的每一件物品
if (j - v[k] >= 0)
f[j] = max(f[j], f[j - v[k]] + w[k];
有依赖的背包#
其实是树形 DP。
咕咕咕。
泛化物品#
在背包容量为
如果给定了两个泛化物品
可以看到,这里的
本文所有代码均未经过编译。
大部分参考 崔天翼《背包九讲》。
Written with StackEdit.
作者:Hszzzx
出处:https://www.cnblogs.com/Hszzzx/p/dp-review.html
版权:本作品采用「署名-非商业性使用-相同方式共享 4.0 国际」许可协议进行许可。
本文来自博客园,作者:HyperV,转载请注明原文链接:https://www.cnblogs.com/Hszzzx/p/dp-review.html
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 【自荐】一款简洁、开源的在线白板工具 Drawnix