只学了01背包、完全背包、多重背包、分组背包这几种。
各背包问题的化简思路
背包问题用的数组可以从二维压缩为一维。压缩为一维时,01背包递推是从高到低(如j--),完全背包是从低到高(如j++),这是从他们的递推关系式得出的。需要考虑低容积用到的是前i-1种还是前i种。一旦用递推式更新,那么当前的f[j]就是考虑到了前i种(假设没更新前只是考虑了前i-1种物品)。循环时,j从高到低减少,那么小于j的所有f都是只考虑到了前i-1种的,符合01背包的递推式;j从低到高增加,那么小于j的所有f都是考虑了前i种的,符合完全背包的递推式。分组背包的一维优化也可以用这个思路来考虑。
前面3种背包问题是对空间进行了优化,而多重背包可以对时间进行优化。具体方法是2进制拆分,把k个相同物品拆成几堆(二级制拆分,保证了这几堆可以选其中的几堆组合成0到k中的所有数字的个数),再把这几堆视为新的不同的物品,再用01背包的思路解决。
线性时间上的背包问题
例子就是洛谷上的P1853(投资的最大收益)和P1095(守望者的逃离)。拿P1853来说,每一年的收益都是一个背包问题,而背包容量就是前一年的本金加上收益,每一年之间的联系实际上并不强烈,用年数作为最外层的循环,每一次循环都需要用到memset函数把背包的数组给清空。而对于P1095来说,每一秒也是在做背包问题,(这里的价值是距离,容积是蓝量,而物品则是可以进行的三个操作,而回蓝操作所占的容积应为-4),但是与P1853不同的是,当前秒数与上一秒之间的联系更紧,因为价值(也就是距离)与上一秒的价值(也就是距离)有关,每一秒循环后不用清空背包的数组。
总的来说,这类问题就是背包问题一种“特殊的叠加”,需要以时间在最外层再套一层循环。