1049. Last Stone Weight II
You are given an array of integers stones where stones[i] is the weight of the ith stone.
We are playing a game with the stones. On each turn, we choose any two stones and smash them together. Suppose the stones have weights x and y with x <= y. The result of this smash is:
If x == y, both stones are destroyed, and
If x != y, the stone of weight x is destroyed, and the stone of weight y has new weight y - x.
At the end of the game, there is at most one stone left.
Return the smallest possible weight of the left stone. If there are no stones left, return 0.
Example 1:
Input: stones = [2,7,4,1,8,1]
Output: 1
Explanation:
We can combine 2 and 4 to get 2, so the array converts to [2,7,1,8,1] then,
we can combine 7 and 8 to get 1, so the array converts to [2,1,1,1] then,
we can combine 2 and 1 to get 1, so the array converts to [1,1,1] then,
we can combine 1 and 1 to get 0, so the array converts to [1], then that’s the optimal value.
思路
题目说的很复杂,但其实本质就是重量相减。
举个例子,把石头分成两堆,A堆有[1,7,4],B堆有[1,8,1]。两堆无论以什么顺序碰撞,最终永远是A堆剩下 12-10 = 2 重量的石头。
所以只需将石头分为重量最接近的两部分,这样两部分相减剩余的值最小。
所以本题可以抽象为01背包问题,背包的容量target为石头总质量的一半sum/2。
stone[i]的重量为stone[i],价值也为stone[i]。
dp[j]表示容量为j的背包能装的最大质量是dp[j]。
对于每个stone[i],有放和不放两种状态,所以dp[j]=max(dp[j], dp[j-stone[i]]+stone[i])。
因为除号向下取整,所以sum-dp[target] >= dp[target],所以答案就是sum-dp[target]-dp[target]
AC代码
class Solution {
public:
int lastStoneWeightII(vector<int>& stones) {
int sum=0;
for(auto data:stones)sum+=data;
int target=sum/2;
vector<int> dp(15001,0);
for(int i=0;i<stones.size();i++)
for(int j=target;j>0;j--)
dp[j]=max(dp[j],dp[j-stone[i]]+stones[i]);
return sum-dp[tatget]-dp[target];
}
};