01背包问题是最经典的动态规划问题,主要要多做才能找到动态规划的划分规则。
01背包问题:
给定 n 件物品,物品的重量为 w[i],物品的价值为 c[i]。现挑选物品放入背包中,假定背包能承受的最大重量为 V,问应该如何选择装入背包中的物品,使得装入背包中物品的总价值最大?
首先是最为朴素的二维DP理解:DP = [[0] * V for _ in range(m)] 即求DP[i][j] 当在前面 i个物品中挑选到 j重量的物品的时候的最大价值为多少
所以动态转移方程为 DP[I][J] = MAX(DP[i-1][j], c[i] + DP[i-1][j-w[i]])
动态规划+压缩空间
观察上面的代码,会发现,当更新dp[i][..]时,只与dp[i-1][..]有关,也就是说,我们没有必要使用O(n*W)的空间,而是只使用O(W)的空间即可。下面先给出代码,再结合图例进行说明。
以6月8号的题目为例
有一堆石头,用整数数组 stones 表示。其中 stones[i] 表示第 i 块石头的重量。
每一回合,从中选出任意两块石头,然后将它们一起粉碎。假设石头的重量分别为 x 和 y,且 x <= y。那么粉碎的可能结果如下:
如果 x == y,那么两块石头都会被完全粉碎;
如果 x != y,那么重量为 x 的石头将会完全粉碎,而重量为 y 的石头新重量为 y-x。
最后,最多只会剩下一块 石头。返回此石头 最小的可能重量 。如果没有石头剩下,就返回 0。
这道题目要转化一下问题。 转化为在 重量限制为总量一半的背包里面装入尽可能重的石头,总量减去2*DP即为目标值。
或者按照背包问题理解一步一步推导: