竟然有人在 V2EX 问算法题,吓到。
先推荐个神犇的博客
hzwer.comDP 的最最主要的部分就是在于状态转移,我们需要求出如何从上一个状态转移到下一个状态,也就是转移方程。
例如背包问题,有一维和二维两种方式,本质都是一样的,但是二维比较好理解,我来说一下。
假设 n 个物品,这 n 个物品的大小在一个数组 weight[n]里面,背包最大装 m ,数组 dp[i][j], i 表示输入中的前 i 个物品, j 表示背包此时大小, dp[i][j]表示有 i 个物品且背包大小为 j 时最多能装多少东西(或者大小,都是一样的)。
首先对某个物品来说,背包的大小肯定不能小于物品大小,否则装不进去了,也就是 dp[i][]中 weight[i] >= j 。接下来,我们在可以想出,要是想装这个物体, dp[i][j]就是 dp[i - 1][j - weight[i]] + 1 ,但实际上,有的物品不装反而最后能满足的更多,那么我们还要判断是 dp[i - 1][j]大还是 dp[i - 1][j - weight[i]] + 1 大,表示到底装不装这个物品大。
这时候还没完,我们发现,在 weight[i] < j 的这时候,其实我们也可以不装此时这个物品,因为装不进去,但是可以把以前能装的的物品装进去,也就是直接赋为 dp[i - 1][j]。
然后跑个两层 for 就好了,最后 dp[n][m]就是答案。
好好自己想想为什么,不要看到题解似懂非懂就做, AC 也没什么用。
总之背包和区间还好,到时候状压会让你怀疑人生的。