背包

背包问题用于解决子集权值和问题,一般会有体积等限制

基本模型

  • 01 背包

这个似乎没啥好说的,注意倒序枚举即可


  • 完全背包

也没啥好说的,改成正序即可


  • 分组背包

注意枚举顺序先组,后倒序体积,最后元素


  • 多重背包

这个直接当成分组背包做肯定是吃不消的
一般常见好写的是二进制拆分,即把那么多物品拆分成 log

来记录一下单调队列优化的方法:
首先写出来转移方程:

f[j]=max1kcf[jkw]+kv

可以发现每个 w 的同余系的转移是独立的,首先用前缀和转化为加法形式

即改写为 f[j]=max(f[d+wk]vk)+vs,其中 scks,典型的滑动窗口了,单调队列来维护

实现见 P1776 宝物筛选


记录一下另一个蓝书上提到的算法,用于 O(nm) 运行 bool 类型的多重背包问题
对于每一种物品,开一个数组 used 表示到达体积 j 最少用几个当前种物品,如果能从 i1 个物品转移为零


  • 退背包

P4141 消失之物

即遵循怎么来的怎么回去
每次将 f 复制到 g,然后 g[j]=g[jw[i]] 即可,注意要正序枚举
注意 max 以及可行性时均不能使用退背包


  • bitset 优化可行性背包

注意到转移方程为 f[j]|=f[ja[i]],那么用 bitset 优化成 f|=f<<a[i]
不用担心 bitsetRE 问题,会自动省略超出的部分


  • 负体积背包

对于负体积的物品,需要改变循环顺序,因为其加减号发生了改变,那么循环顺序相当于还是保证了转移顺序


  • 大容量背包

对于容量很大,而物品体积很小的背包,可以先贪心用性价比最高的选择到 w 的体积,剩余的跑暴力


例题

P1941 [NOIP2014 提高组] 飞扬的小鸟

算是藏得比较深的背包题,要学会转化


CF687C The Values You Can Make

背包问题的变形
f[j][k] 表示和为 j 且子集和为 k 可不可行
那么有两种转移,即每个放入 j 的数放不放入 k
那么 f[j][k]|=f[ja[i]][ka[i]]
以及 f[j][k]|=f[ja[i]][k]


CF1442D Sum

可以发现不选完的序列最多一个
那么枚举每一个序列的前几个,和剩下的背包合并
可以发现这个并不能退背包,那么采用类似于 CDQ 分治的套路,递归左区间则把右区间放入,否则放左区间


P3188 [HNOI2007]梦幻岛宝珠

大体积背包,数据范围还不能折半搜索
那必然有特殊要求啦,就是 a×2b

考虑一位一位进行 dp,设 f[i][j] 表示 b=i 的物品的 a 所占用 j 体积的背包价值,g[i][j] 表示前 i 个物品,且相对于第 i 位体积为 j 的最大价值

考虑转移,f 的转移很常规,g 的转移:

g[i][j]=f[i][jk]+g[i1][2k+((m>>(i1))&1)]

相当于是当前位的体积过渡到下一个的过程,一个顶俩


AT4120 [ARC096D] Sweet Alchemy

考虑每次选择一个子树,只要 cid 就可以满足次数条件
此时就变成了一个多重背包问题
可以发现体积很大而价值很小,使用一种非常神奇的方法:
对于每个物品选出 n 个来跑多重背包的 dp ,其余的直接性价比排序贪心来选,这样就不会带来整除对答案的影响了
其中需要交换体积和价值的下标


P8392 [BalticOI 2022 Day1] Uplifting Excurs

这个也是类似的问题,可以先通过贪心把值域缩小到 m2dp 范围
有负数时,可以先贪心地把负数都选上,然后最后再在做背包的时候去掉

posted @   y_cx  阅读(61)  评论(0编辑  收藏  举报
(评论功能已被禁用)
编辑推荐:
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
阅读排行:
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
· 为什么 退出登录 或 修改密码 无法使 token 失效
点击右上角即可分享
微信分享提示