This commit is contained in:
parent
43be72324d
commit
8551696b52
14
include/s1049_last_stone_weight_ii.hpp
Normal file
14
include/s1049_last_stone_weight_ii.hpp
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
#ifndef S1049_LAST_STONE_WEIGHT_II_HPP
|
||||||
|
#define S1049_LAST_STONE_WEIGHT_II_HPP
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
class S1049 {
|
||||||
|
public:
|
||||||
|
int lastStoneWeightII(vector<int>& stones);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
@ -7,7 +7,7 @@
|
|||||||
1. 确定 `dp[i]` 是什么
|
1. 确定 `dp[i]` 是什么
|
||||||
2. 确定递推公式
|
2. 确定递推公式
|
||||||
3. `dp` 数组如何初始化
|
3. `dp` 数组如何初始化
|
||||||
4. 确定遍历顺序(从前向后还是从后向前)
|
4. 确定遍历顺序(从前向后还是从后向前)和范围
|
||||||
5. 推几个来验证
|
5. 推几个来验证
|
||||||
|
|
||||||
技巧:
|
技巧:
|
||||||
|
@ -124,3 +124,38 @@ void bag_problem_1d() {
|
|||||||
- 遍历顺序:
|
- 遍历顺序:
|
||||||
- `i` 从前往后,范围是 `1 <= i < length`
|
- `i` 从前往后,范围是 `1 <= i < length`
|
||||||
- `j` 从后往前,范围是 `nums[i] <= j <= target`
|
- `j` 从后往前,范围是 `nums[i] <= j <= target`
|
||||||
|
|
||||||
|
本题中可以不初始化第一层,然后 `i` 从 0 开始。
|
||||||
|
|
||||||
|
## [1049. 最后一块石头的重量 II](https://leetcode.cn/problems/last-stone-weight-ii/)
|
||||||
|
|
||||||
|
仔细思考一下每个石头重量的加减方式,你会发现其实最终的重量可以这样表示:
|
||||||
|
|
||||||
|
`final = k0 * w0 + k1 * w1 + k2 * w2 + ...`
|
||||||
|
|
||||||
|
其中 `ki` 为 `+1` 或 `-1`,`wi` 为第 `i` 个石头的重量。
|
||||||
|
|
||||||
|
那么 `ki` 取负的所有石头重量之和我们表示为 `neg`,其它石头重量之和为 `total - neg`。
|
||||||
|
|
||||||
|
我们的目的就是要在 `neg <= total/2` 的前提下,让 `neg` 达到最大。
|
||||||
|
|
||||||
|
这就是一个 01 背包问题。
|
||||||
|
|
||||||
|
- `i` 对应石头下标,每个石头的重量为 `stones[i]`,价值为 `stones[i]`
|
||||||
|
- `j` 对应背包容量,最大为 `total/2`
|
||||||
|
|
||||||
|
我们直接上滚动数组:
|
||||||
|
|
||||||
|
- `dp[j]` 表示从 0 ~ i 中选石头,放进容量为 `j` 的背包,所能达到的最大价值
|
||||||
|
- 迭代公式:
|
||||||
|
- `if (j < stones[i]) dp[j] = dp[j]`
|
||||||
|
- `if (j >= stones[i]) dp[j] = max{dp[j], dp[j - stones[i]] + stones[i]}`
|
||||||
|
- 第二层迭代的范围是 `stones[i] ~ total/2`
|
||||||
|
- 初始化:
|
||||||
|
- `if (j < stones[0]) dp[j] = 0`
|
||||||
|
- `if (j >= stones[0]) dp[j] = stones[0]`
|
||||||
|
- 遍历:
|
||||||
|
- `i` 从 1 到 length - 1
|
||||||
|
- `j` 从 `total/2` 向下取整,遍历到 `stones[i]`
|
||||||
|
|
||||||
|
本题中可以不初始化第一层,然后 `i` 从 0 开始。
|
||||||
|
15
src/s1049_last_stone_weight_ii.cpp
Normal file
15
src/s1049_last_stone_weight_ii.cpp
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
#include "s1049_last_stone_weight_ii.hpp"
|
||||||
|
|
||||||
|
int S1049::lastStoneWeightII(vector<int>& stones) {
|
||||||
|
int total{0};
|
||||||
|
int len = stones.size();
|
||||||
|
vector<int> dp(30 * 1000 / 2 + 1, 0);
|
||||||
|
for (int i{0}; i < len; ++i) total += stones[i];
|
||||||
|
int limit = total >> 1;
|
||||||
|
for (int i{0}; i < len; ++i) {
|
||||||
|
for (int j = limit; j >= stones[i]; --j) {
|
||||||
|
dp[j] = max(dp[j], dp[j - stones[i]] + stones[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return total - dp[limit] * 2;
|
||||||
|
}
|
24
tests/s1049_last_stone_weight_ii.cpp
Normal file
24
tests/s1049_last_stone_weight_ii.cpp
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
#include "s1049_last_stone_weight_ii.hpp"
|
||||||
|
|
||||||
|
#include <gtest/gtest.h>
|
||||||
|
|
||||||
|
TEST(Problem1049, Case1) {
|
||||||
|
vector<int> stones{2, 7, 4, 1, 8, 1};
|
||||||
|
int expected{1};
|
||||||
|
S1049 solution;
|
||||||
|
EXPECT_EQ(solution.lastStoneWeightII(stones), expected);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(Problem1049, Case2) {
|
||||||
|
vector<int> stones{31, 26, 33, 21, 40};
|
||||||
|
int expected{5};
|
||||||
|
S1049 solution;
|
||||||
|
EXPECT_EQ(solution.lastStoneWeightII(stones), expected);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(Problem1049, Case3) {
|
||||||
|
vector<int> stones{57, 32, 40, 27, 35, 61};
|
||||||
|
int expected{4};
|
||||||
|
S1049 solution;
|
||||||
|
EXPECT_EQ(solution.lastStoneWeightII(stones), expected);
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user