方法:动态规划(转化为01背包)
--二维数组
class Solution {
public int lastStoneWeightII(int[] stones) {
//转化为01背包问题:尽量让石头分成重量相同的两堆,粉碎之后重量最小
int sum = 0;
for (int stone : stones) {
sum += stone;
}
int n = stones.length;
int target = sum / 2;
//dp[i][j]表示可以放0-i物品,背包容量为j的情况下背包中的最大价值
int[][] dp = new int[n][target + 1];
//dp[i][0]默认初始化为0
//dp[0][j]初始化为stones[0]
for (int j = stones[0]; j <= target; j++) {
dp[0][j] = stones[0];
}
for (int i = 1; i < n; i++) {
for (int j = 1; j <= target; j++) {
if (j < stones[i]) {
dp[i][j] = dp[i - 1][j];
} else {
dp[i][j] = Math.max(dp[i - 1][j], dp[i - 1][j - stones[i]] + stones[i]);
}
}
}
//最后dp[n - 1][target]里是容量为target的背包所能背的最大重量
//那么分成两堆石头,一堆石头的总重量是dp[n - 1][target],另一堆就是sum - dp[n - 1][target]
//由于target = sum / 2 是向下取整,所以sum - dp[n - 1][target] 一定是大于等于dp[n - 1][target]的
return sum - dp[n - 1][target] - dp[n - 1][target];
}
}
--一维数组
class Solution {
public int lastStoneWeightII(int[] stones) {
//转化为01背包问题:尽量让石头分成重量相同的两堆,粉碎之后重量最小
int sum = 0;
for (int stone : stones) {
sum += stone;
}
int n = stones.length;
int target = sum / 2;
//dp[j]表示可以放0-i物品,背包容量为j的情况下背包中的最大价值
int[] dp = new int[target + 1];
//dp[j]默认初始化为0
for (int i = 0; i < n; i++) {
for (int j = target; j >= stones[i]; j--) {
dp[j] = Math.max(dp[j], dp[j - stones[i]] + stones[i]);
}
}
//最后dp[target]里是容量为target的背包所能背的最大重量
//那么分成两堆石头,一堆石头的总重量是dp[target],另一堆就是sum - dp[target]
//由于target = sum / 2 是向下取整,所以sum - dp[target] 一定是大于等于dp[target]的
return sum - dp[target] - dp[target];
}
}