1.题目描述:
有一堆石头,用整数数组stones表示。其中stones[i]表示第i块石头的重量。每一回合,从中选出任意两块石头,然后将它们一起粉碎。假设石头的重量分别为x和y,且x <= y。那么粉碎的可能结果如下:如果 x == y,那么两块石头都会被完全粉碎;如果x != y,那么重量为x的石头将会完全粉碎,而重量为y的石头新重量为y-x。最后,最多只会剩下一块石头。返回此石头最小的可能重量。如果没有石头剩下,就返回0。
2.动态规划:
转化为01背包问题:仔细一想,其实就是操作所有的石头进行加减操作,符号随意,得到的最小值。将石头分为重量总和接近的两堆(参考分割等和子集),向下取整,右边大的减去左边小的即为最小值。直接一维dp数组:
class Solution {
public int lastStoneWeightII(int[] stones) {
int sum = 0;
for (int i = 0; i < stones.length; i++) {
sum += stones[i];
}
int bpSize = sum / 2;
int gZize = stones.length;
int[] dp = new int[bpSize + 1];
for (int i = 0; i < gZize; i++) {
for (int j = bpSize; j >= stones[i]; j--) {
dp[j] = Math.max(dp[j], dp[j - stones[i]] + stones[i]);
}
}
return sum - dp[bpSize] - dp[bpSize];
}
}