背包DP
0-1背包
问题:有 个物品和一个容量为 的背包,每个物品有重量 和价值 两种属性,要求选若干物品放入背包使背包中物品的总价值最大且背包中物品的总重量不超过背包的容量。
每个物品只有取和不取两种选择,所以称为0-1背包问题。
设DP状态为只放前个物品的情况下,容量为的背包可以达到的最大价值。则有:
这样的话状态是一个二维数组,直接的一个优化是观察到只和有关系,所以可以去掉这一维,直接在上面做状态的更新,也就是:
这样就把状态简化成了一维,节省了大量内存。要注意的是,因为依赖,所以更新的时候,需要从大到小更新,才能不覆盖后面需要使用到的值。
模板代码:
for (int i = 1; i <= n; i++)
for (int l = W; l >= w[i]; l--)
f[l] = max(f[l], f[l - w[i]] + v[i]);
更多背包
关于完全背包、多重背包、混合背包等,请参照OI-Wiki。
习题
习题 | ||||||
---|---|---|---|---|---|---|
T200147 | 通天之分组背包 | 普及- | ||||
T204510 | 越越的组队 | 普及- | ||||
T204512 | 榨取kkksc03 | 普及- | ||||
T200143 | 深基12.例1 | 部分背包问题 | 普及/提高- | |||
T200145 | USACO | 集合 Subset Sums | 普及/提高- | |||
T191609 | NOIP-S | 金明的预算方案 | 2006 | 普及+/提高 | ||
T191608 | SNOI | 英雄联盟 | 2017 | 普及+/提高 | ||
CF543A | CF | Writing Code | 普及+/提高 | |||
T191967 | NOIP-S | 飞扬的小鸟 | 2014 | 普及+/提高 | ||
CF1381B | CF | Unmerge | 普及+/提高 | |||
T205905 | 不开心的金明 | 普及+/提高 | ||||
CF577B | CF | Modulo Sum | 提高+/省选- | |||
T205880 | HNOI | 产品加工 | 2001 | 提高+/省选- |