LeetBook刷题笔记021:最后一块石头II(Java实现)
题目
有一堆石头,用整数数组 stones 表示。其中 stones[i] 表示第 i 块石头的重量。
每一回合,从中选出任意两块石头,然后将它们一起粉碎。假设石头的重量分别为 x 和 y,且 x <= y。那么粉碎的可能结果如下:
如果 x == y,那么两块石头都会被完全粉碎;
如果 x != y,那么重量为 x 的石头将会完全粉碎,而重量为 y 的石头新重量为 y-x。
最后,最多只会剩下一块 石头。返回此石头最小的可能重量 。如果没有石头剩下,就返回 0。
最优解:动态规划(01背包)
- 将问题抽象
- 求此石头最小的可能重量
- 将石头分成重量最靠近石头重量和一半的两堆
- 求其中一堆(可以借此求出另一堆)
- 求重量最靠近总和一半的石头堆
- 转换为01背包问题
- 总量:石头重量和的一半
- 价值:石头重量
- 体积:石头重量
- 代入模板
public int lastStoneWeightII(int[] stones) {
int n =stones.length;
int sum = 0;
for(int i=0;i<n;i++)
sum += stones[i];
sum /= 2;
int[] dp = new int[sum+1];
for(int i=0;i<n;i++){
for(int t=sum;t>=stones[i];t--)
dp[t] = Math.max(dp[t],dp[t-stones[i]]+stones[i]);
}
return sum-dp[sum];
}