Day36
1049. 最后一块石头的重量 II
思路
把石头尽可能分成两堆,这两堆重量如果相似,相撞后所剩的值就是最小值
若石头的总质量为sum,可以将问题转化为0-1背包问题,即给一个容量为sum/2的容器,如何尽量去凑满这个容器
此题和分割等和子集类似
class Solution { public: int lastStoneWeightII(vector<int>& stones) { vector<int> dp(15001, 0); int sum = 0; for (int i = 0; i < stones.size(); i++) sum += stones[i]; int target = sum / 2; for (int i = 0; i < stones.size(); i++) { // 遍历物品 for (int j = target; j >= stones[i]; j--) { // 遍历背包 dp[j] = max(dp[j], dp[j - stones[i]] + stones[i]); } } return sum - dp[target] - dp[target]; } };
思考
循环中,为什么是“j >= stones[i]”?
如果石头的重量stones[i]大于背包的容量j,就不用去遍历了
最终的结果为什么是"sum - dp[target] - dp[target]"?
第一堆石头的重量为dp[target],第二堆石头的重量自然为sum - dp[target],又因为计算target的时候,是除以2并向下取整,所以sum - dp[target]一定比dp[target]要大,最终的结果就是第二堆石头的重量减去第一堆石头的重量
五部曲
1.dp数组及下标定义:dp数组的大小根据题目条件,sum最大的值为3000,所以长度定义为sum/2也就是1500;dp[j],表示装满容量为j的背包需要的最大重量为dp[j]
2.递推公式:dp[j] = max(dp[j], dp[j-stone[i]] + stone[i])
3.初始化:dp数组都初始化为0
4.遍历顺序:第一层循环遍历物品,第二层循环遍历背包
5.数组的数据应该是怎样的: