缘由
这是一个早就想解决的问题,曾经做01背包的练习就是单纯地套用模板,近期看到一篇很好的文章,又有了新的一些体悟,特此记录。
状态函数及状态转移方程:
函数
表示考虑前 个物品,设定总空间为 时的最大价值。
误区纠正:学习方法
之前学习算法(尤其是DP),总是觉得自己应该整体上“理解”这个算法,而忽略了从列表、特殊数据等方面来辅助学习的方法。其实,如果对01背包问题感到难以理解,多半是因为不愿意认真列表分析一个特例。
状态函数
函数
定义很清晰,但是理解时可能会不经意间进入下列误区:
- 对
的理解,应当是考察了前 个物品,并不是说这前 个物品都进入了背包; - 对
的理解,是考察前 个物品时,赋予的总空间,而不是所谓“剩余空间”; - 所给空间
并不一定要恰好填满,而是不能超过。
状态转移方程
与 比较大小时,考察的是“就算把空间全都给第 件物品,它能不能放进去”,体现的是一种优先思想,即优先考虑第 件物品。先决定它放不放进去,然后再说编号 的物品如何处理。在这样的操作方法下,当第 件物品是否放入背包已经确定时, 最大的情况就等价于考察前 件物品最大时的情况。
时空复杂度的优化
该部分参考了dd_engi大佬的背包九讲
原问题较为显然的实现应当是定义二维数组
先上一张图,便于下面进行描述。
空间复杂度的优化
注意到,在外层循环进行到某个特定的
利用这一特性,不妨将数组减去一维,即将
时间复杂度的优化
上面应该注意到,公式的
这一条并没有体现出来。
事实上,当
变形:分组背包
与传统01背包不同之处在于每次决策是决定是否从一组中拿一个物品,以及拿哪个(每一组中的物品最多只能拿一件)。
解决方法:略作变形,在决定
总结
01背包可能是最经典、最简单的动态规划问题了。理解好这一模型的方法、思路、技巧,对后续动态规划的进一步学习应当有较大帮助。
Last modified on 2020-05-14