4242
4343## 思路
4444
45- 如果对背包问题不都熟悉先看这两篇 :
45+ 如果对背包问题不熟悉的话先看这两篇 :
4646
47- * [ 动态规划:关于01背包问题,你该了解这些! ] ( https://programmercarl.com/背包理论基础01背包-1.html )
48- * [ 动态规划:关于01背包问题,你该了解这些!(滚动数组 )] ( https://programmercarl.com/背包理论基础01背包-2.html )
47+ * [ 01背包理论基础(二维数组) ] ( https://programmercarl.com/背包理论基础01背包-1.html )
48+ * [ 01背包理论基础(一维数组 )] ( https://programmercarl.com/背包理论基础01背包-2.html )
4949
50- 本题其实就是尽量让石头分成重量相同的两堆,相撞之后剩下的石头最小, ** 这样就化解成01背包问题了 ** 。
50+ 本题其实是尽量让石头分成重量相同的两堆(尽可能相同),相撞之后剩下的石头就是最小的。
5151
52- 是不是感觉和昨天讲解的[ 416. 分割等和子集] ( https://programmercarl.com/0416.分割等和子集.html ) 非常像了。
52+ 一堆的石头重量是sum,那么我们就尽可能拼成 重量为 sum / 2 的石头堆。 这样剩下的石头堆也是 尽可能接近 sum/2 的重量。
53+ 那么此时问题就是有一堆石头,每个石头都有自己的重量,是否可以 装满 最大重量为 sum / 2的背包。
5354
54- 本题物品的重量为stones [ i ] ,物品的价值也为stones [ i ] 。
55+ 看到这里,大家是否感觉和昨天讲解的 [ 416. 分割等和子集 ] ( https://programmercarl.com/0416.分割等和子集.html ) 非常像了,简直就是同一道题 。
5556
56- 对应着01背包里的物品重量weight[ i] 和 物品价值value[ i] 。
57+ 本题** 这样就化解成01背包问题了** 。
58+
59+ ** [ 416. 分割等和子集] ( https://programmercarl.com/0416.分割等和子集.html ) 是求背包是否正好装满,而本题是求背包最多能装多少** 。
60+
61+ 物品就是石头,物品的重量为stones[ i] ,物品的价值也为stones[ i] 。
5762
5863接下来进行动规五步曲:
5964
60- 1 . 确定dp数组以及下标的含义
65+ ### 1. 确定dp数组以及下标的含义
6166
6267** dp[ j] 表示容量(这里说容量更形象,其实就是重量)为j的背包,最多可以背最大重量为dp[ j] ** 。
6368
64- 可以回忆一下01背包中,dp [ j ] 的含义,容量为j的背包,最多可以装的价值为 dp [ j ] 。
69+ 相对于 01背包,本题中,石头的重量是 stones [ i ] ,石头的价值也是 stones [ i ] 。
6570
66- 相对于 01背包,本题中,石头的重量是 stones [ i ] ,石头的价值也是 stones [ i ] ,可以 “最多可以装的价值为 dp[ j] ” == “最多可以背的重量为dp[ j] ”
71+ “最多可以装的价值为 dp[ j] ” 等同于 “最多可以背的重量为dp[ j] ”
6772
68- 2 . 确定递推公式
73+ ### 2. 确定递推公式
6974
707501背包的递推公式为:dp[ j] = max(dp[ j] , dp[ j - weight[ i]] + value[ i] );
7176
7277本题则是:** dp[ j] = max(dp[ j] , dp[ j - stones[ i]] + stones[ i] );**
7378
74- 一些同学可能看到这dp[ j - stones[ i]] + stones[ i] 中 又有- stones[ i] 又有+stones[ i] ,看着有点晕乎。
75-
76- 大家可以再去看 dp[ j] 的含义。
77-
78- 3 . dp数组如何初始化
79+ ### 3. dp数组如何初始化
7980
8081既然 dp[ j] 中的j表示容量,那么最大容量(重量)是多少呢,就是所有石头的重量和。
8182
9596vector<int> dp(15001, 0);
9697```
9798
98- 4 . 确定遍历顺序
99+ ### 4. 确定遍历顺序
99100
100101
101102在[ 动态规划:关于01背包问题,你该了解这些!(滚动数组)] ( https://programmercarl.com/背包理论基础01背包-2.html ) 中就已经说明:如果使用一维dp数组,物品遍历的for循环放在外层,遍历背包的for循环放在内层,且内层for循环倒序遍历!
@@ -111,7 +112,7 @@ for (int i = 0; i < stones.size(); i++) { // 遍历物品
111112
112113```
113114
114- 5 . 举例推导dp数组
115+ ### 5. 举例推导dp数组
115116
116117举例,输入:[ 2,4,1,1] ,此时target = (2 + 4 + 1 + 1)/2 = 4 ,dp数组状态图如下:
117118
@@ -154,10 +155,7 @@ public:
154155
155156本题其实和[416. 分割等和子集](https://programmercarl.com/0416.分割等和子集.html)几乎是一样的,只是最后对dp[target]的处理方式不同。
156157
157- [416. 分割等和子集](https://programmercarl.com/0416.分割等和子集.html)相当于是求背包是否正好装满,而本题是求背包最多能装多少。
158-
159-
160-
158+ **[416. 分割等和子集](https://programmercarl.com/0416.分割等和子集.html)相当于是求背包是否正好装满,而本题是求背包最多能装多少**。
161159
162160
163161## 其他语言版本
0 commit comments