随想录训练营Day40 | DP - - 背包理论基础, 416. 分割等和子集

49 阅读1分钟

随想录训练营Day40 | DP - - 背包理论基础, 416. 分割等和子集

标签: LeetCode闯关记


背包理论基础(一): 二维数组

public class TestBackTracing {
    private static void find(int[] weight, int[] value, int n,int w) {
        int[][] dp = new int[n][w+1];//dp[i][j] 表示从下标为[0-i]的物品里任意取,放进容量为j的背包,价值总和最大是多少
        //初始化
        //1)从下标为[0-i]的物品里任意取,放进容量为j=0的背包 的最大价值
        for (int i = 0; i < dp.length; i++) {
            dp[i][0] = 0;
        }
        //2)将重量为weight[0]的物品放入容量为j的背包的最大价值
        for (int j = 0; j < dp[0].length; j++) {
            if(j >= weight[0]){
                dp[0][j] = value[0];
            }else dp[0][j] = 0;
        }
        for (int i = 1; i < dp.length; i++) {//先遍历物品
            for (int j = 1; j < dp[i].length; j++) {//再遍历背包重量
                if(j < weight[i]){//不放当前物品,因为当前要放入的物品重量 > 背包容量
                    dp[i][j] = dp[i-1][j];
                }else{
                    //假设背包可放入当前物品: 那么分为两种情况---放 or 不放
                    dp[i][j] = Math.max(dp[i-1][j],dp[i-1][j- weight[i]] + value[i]);
                }
            }
        }
        System.out.println(dp[n-1][w]);
    }

    public static void main(String[] args) {
        int[] weight = {1,3,4}; // 物品重量数组
        int[] value = {15,20,30}; // 物品价值数组
        int n = 3; // 物品数量
        int w = 4; //
        find(weight,value,n,w);// 背包最大承重
    }
}

背包理论基础(二): 一维数组(滚动数组)

笔记img_40_1.png

public class BagWeight {
    public static void main(String[] args) {
        int[] weight = {1, 3, 4};
        int[] value = {15, 20, 30};
        int bagWeight = 4;
        testWeightBagProblem(weight, value, bagWeight);
    }
    public static void testWeightBagProblem(int[] weight, int[] value, int bagWeight){
        int[] dp = new int[bagWeight+1];
        int len = dp.length;
        for (int i = 0; i < len; i++) {
            dp[i] = 0;
        }
        for (int i = 0; i < weight.length; i++) {
            for (int j = bagWeight; j >= weight[i] ; j--) {
                dp[j] = Math.max(dp[j], dp[j-weight[i]] + value[i]);
            }
        }
        System.out.println(dp[bagWeight]);
    }
}

416. 分割等和子集

问题: 理解不了一维数组的方法(内外层循环) + 完全想不到是背包问题

class Solution {
    public boolean canPartition(int[] nums) {
        int sum = 0;
        for (int i = 0; i < nums.length; i++) {
            sum += nums[i];
        }
        if(sum % 2 != 0) return false;
        int target = sum/2;

        int[] dp = new int[target+1];//找sum和为i的子集;
        for (int i = 0; i < dp.length; i++) {
            dp[i] = 0;
        }
        for (int i = 0; i < nums.length; i++) {//搞不懂这里咋回事
            for (int j = target; j >= nums[i] ; j--) {
                dp[j] = Math.max(dp[j],dp[j- nums[i]] + nums[i]);
            }
        }
        return dp[target] == target;
    }
}