📝

Leetcode 1049

Importance
📗📗📗📗
Start Date
Mar 31, 2025 21:25
tags
Dynamic Programming
01-Backpack
Link:

题目要求

有一堆石头,用整数数组 stones 表示。其中 stones[i] 表示第 i 块石头的重量。
每一回合,从中选出任意两块石头,然后将它们一起粉碎。假设石头的重量分别为 x 和 y,且 x <= y。那么粉碎的可能结果如下:
  • 如果 x == y,那么两块石头都会被完全粉碎;
  • 如果 x != y,那么重量为 x 的石头将会完全粉碎,而重量为 y 的石头新重量为 y-x
最后,最多只会剩下一块 石头。返回此石头 最小的可能重量 。如果没有石头剩下,就返回 0
 

核心算法和原理

  • 求的其实是:将石头尽可能分成质量接近的两堆,这两堆石头的差即为最小值
  • dp[i][j]:从前i个石头中选石头,能否组成总质量为j的石头堆
 

代码

class Solution { public: int lastStoneWeightII(vector<int>& stones) { int n = stones.size(); int sum = 0; for (int s: stones) { sum += s; } int target = sum / 2; vector<bool> dp(target + 1, false); dp[0] = true; int curSum = 0; for (int i = 0; i < n; i++) { curSum += stones[i]; for (int j = min(curSum, target); j >= stones[i]; j--) { dp[j] = dp[j] || dp[j - stones[i]]; } if (dp[target]) { return (sum - target) - target; } } for (int i = target; i > 0; i--) { if (dp[i]) { return (sum - i) - i; } } // only one element return stones[0]; } };