视频讲解:https://www.bilibili.com/video/BV14M411C7oV/?vd_source=a935eaede74a204ec74fd041b917810c
文档讲解:https://programmercarl.com/1049.最后一块石头的重量II.html#思路
力扣题目: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
- 遍历。二维表中最上一行往最下一行遍历
- 打印数组
一维写法:
cpp
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]);
}
};
二维写法:
cpp
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]));
}
};