题目描述


这个问题如何变成0-1背包问题呢?且听我慢慢分析
假如我们把这个例子进行划分【2,7,4,1,8,1】
我们将其划分为两块石头【4,7】 和为11与【2,1,1,8】和为12,那么他们粉碎后石头的大小为 1。
巧了吧跟答案是一模一样的。
因此我们将背包大小设置为 数组和的一半 = target。
dp动态数组大小也确定了[target + 1];
更新策略跟01背包的更新策略是一致的。
dp[j] = max(dp[j], dp[j - stones[i]] + stones[i]);
结果如何返回呢?
sum - 2*dp[target];
为什么是这样呢?
我们先说一下dp[target]表示的含义,在背包大小为target时,能装的石头的总价值。
为什么要减去2倍的dp[target]呢?因为要粉碎,包里的石头与未装到包里的石头相消,包里石头是dp[target],那么未装到包里的也要消去dp[target],因此才是剩余的。
- package db;
-
- import java.util.Arrays;
-
- public class LastStoneWeightII {
- public static void main(String[] args) {
- int[] stones = {2,7,4,1,8,1};
- int i = lastStoneWeightII(stones);
- System.out.println("i = " + i);
- }
- public static int lastStoneWeightII(int[] stones) {
- int sum = 0;
- for (int stone : stones) {
- sum += stone;
- }
- // 确定背包大小。
- int target = sum / 2;
- int[] dp = new int[target + 1];
- for (int i = 0; i < stones.length; i++) {
- for (int j = target; j >= stones[i]; j--) {
- dp[j] = Math.max(dp[j],stones[i] + dp[j - stones[i]]);
-
- }
- System.out.println(Arrays.toString(dp));
- }
- return sum - 2 * dp[target];
- }
-
- }