【代码随想录day 35】 力扣 1049. 最后一块石头的重量 II
视频讲解:https://www.bilibili.com/video/BV14M411C7oV/?vd_source=a935eaede74a204ec74fd041b917810c
文档讲解:https://programmercarl.com/1049.%E6%9C%80%E5%90%8E%E4%B8%80%E5%9D%97%E7%9F%B3%E5%A4%B4%E7%9A%84%E9%87%8D%E9%87%8FII.html#%E6%80%9D%E8%B7%AF
力扣题目:https://leetcode.cn/problems/last-stone-weight-ii/
这道题本质上还是个01背包问题,本质上可以计算背包容量为sum / 2 的背包最大能装多少价值的东西,sum - dp[j]即为另一半的价值,再减去dp[j]即为两边的差
- dp含义:dp[j]表示容量为j的背包能装0-i的物品的最大价值
- 递推公式:在一维数组的基础上进行更新dp[j] = max(dp[j], dp[j- stones[i]] + stones[i]);
- 初始化,可以同遍历一起,初始化为0
- 遍历。二维表中最上一行往最下一行遍历
- 打印数组
一维写法:
class Solution {
public:int lastStoneWeightII(vector<int>& stones) {int sum = 0;for(int i : stones){sum += i;}int target = sum / 2;//本质上是一个看是否能装满sum/2的题,//1. dp[j]含义:在容量为j的背包里stone[i]能装的最多的价值vector<int> dp(target + 1, 0);//2. 递推公式:dp[j] = max(dp[j], dp[j- stones[i]] + stones[i]);//3.初始化:初始化二维数组的最上一行和最左一列//4.遍历方式:从后往前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 - 2 * dp[target]);}
};
二维写法:
int lastStoneWeightII(vector<int>& stones) {int sum = 0;for(int i : stones){sum += i;}int target = sum / 2;//本质上是一个看是否能装满sum/2的题,//1. dp[i][j]含义:在容量为j的背包里stone能装的最多的价值vector<vector<int>> dp(stones.size(), vector<int>(target + 1, 0));//2. 递推公式:dp[i][j] = max(dp[i - 1][j], dp[i - 1][j- stones[i]] + stones[i]);//3.初始化:初始化二维数组的最上一行和最左一列for(int i = 0; i < stones.size(); ++i){dp[i][0] = 0;}for(int j = 0; j <= target; ++j){if(j >= stones[0]){dp[0][j] = stones[0];}}//遍历从上往下从左往右for(int i = 1; i < stones.size(); ++i){for(int j = 1; j <= target; ++j){if(j < stones[i]){dp[i][j] = dp[i - 1][j];}else{dp[i][j] = max(dp[i - 1][j], dp[i - 1][j- stones[i]] + stones[i]);}//cout << "i,j:" << dp[i][j] << endl;}}return (abs(sum - 2 * dp[stones.size() - 1][target]));}
};