动态规划
如果某一问题有很多重叠子问题,且中每一个状态一定是由上一个状态推导出来的,是用动态规划会最优。贪心只需要考虑局部最优即可。
基本步骤
-
状态转移数组dp[i]内容和下标i的含义确定
-
递推公式的划分和确定
ps: 前两步根据结果来确定dp存储的值/递推公式的形式,一般有最大值/最小值/总方案数三种情况,对应存储值或方案数,递推公式也对应max,min,累加形式。
-
状态转移数组配合递推公式的初始化
-
确定遍历下标的顺序
-
举例推导(打印或模拟)dp数组
01背包
给定的值时物品价值,这里衍生问题最重要的是确定背包容量即bigSize, 然后0~bigSize每种体积都对应一种状态,这些状态都由前面的转移过来。这里有注意的点
- 滚动数组的使用
一开始想到的dp二维数组dp[0…i][j]表示的是任选第i件物品时体积为j的背包存储的目标值。但把0~i-1看成i层的话,下一层的结果完全是由上一层的物品结果转化过来的,因此我们只用一维记录体积,让i不停在原基础上向下滚动即可。为节省空间统一采用滚动数组记录。
- 初始化的方式
如果目标值是最大值或最小值:无为时为0;
如果目标值是方案数:无为时也算一种方案。
- 遍历下标的顺序(主要是对每个体积的遍历顺序)
如果对于一个固定的物品,我们从小到大遍历更新dp值的话,那么只要满足背包容量限制,该物品都会被加进去,但由于每件物品只能使用一次,每次加进去不符题意,故从大到小遍历,此时当前层,比目前遍历到的体积小的背包状态还是上一层物品的目标值,尚未更新加入当前物品,从这种状态转移过来才正确。
- 物品还是体积在外层循环
通过3的逻辑发现如果体积在外面,每个背包里只会放一个体积符合当前背包的最大价值物品,可以模拟一下。所以01背包只能是物品在外层循环,体积在内层循环
未完待续…