背包问题初步总结--01背包,完全背包,有顺序的完全背包

public class TestBeiBao2 {
    //常见的背包问题有1、组合问题。2、True、False问题。3、最大最小问题。
    //1组合问题:dp[i]+=dp[i-num]
    //2true,false问题:dp[i] = dp[i] or dp[i-num]
    //3最大最小问题:dp[i] = min(dp[i], dp[i-num]+value[num])或者dp[i] = max(dp[i], dp[i-num]+value[num])

    //常见解法
    //1分析是否为背包问题
    //2是以上三种背包问题中的哪一种
    //3是0-1背包问题还是完全背包问题。也就是题目给的nums数组中的元素是否可以重复使用
    //4如果是组合问题,是否需要考虑元素之间的顺序。需要考虑顺序有顺序的解法,不需要考虑顺序又有对应的解法

    //常见技巧
    //1如果是0-1背包,即数组中的元素不可重复使用,nums放在外循环,target在内循环,且内循环倒序;
    //2如果是完全背包,即数组中的元素可重复使用,nums放在外循环,target在内循环,且内循环正序;或者target在外循环,nums放在内循环,且内循环正序
    //3如果组合问题需考虑元素之间的顺序,需要在上面两者情况中选择一种,记住:当外层循环遍历nums时说明nums只可能按遍历顺序排列

    //常见问题
    //1典型01背包
    //一维数组(滚动数组)01背包
    public static void testWeightBagProblem(int[] weight, int[] value, int bagWeight) {
        int wLen = weight.length;
        //定义dp数组:dp[j]表示背包容量为j时,能获得的最大价值
        int[] dp = new int[bagWeight + 1];
        //遍历顺序:先遍历物品,再遍历背包容量
        for (int i = 0; i < wLen; i++) {
            for (int j = bagWeight; j >= weight[i]; j--) {
                dp[j] = Math.max(dp[j], dp[j - weight[i]] + value[i]);
            }
        }

        for (int i = 0; i <= bagWeight; i++) {
            System.out.println(dp[i]);
        }
    }

    @Test
    public void test1() {
        int[] weight = {1, 3, 4};//重量 2 3 4 5 9
        int[] value = {15, 20, 30};//价值3 4 5 8 10
        int bagWight = 4;
        testWeightBagProblem(weight, value, bagWight);
    }

    //2典型完全背包
    public void testCompletePackAnotherWay(int[] weight, int[] value, int bagWeight) {
        int wLen = weight.length;
        int[] dp = new int[bagWeight + 1];
        //以下两者遍历方式都行
        //遍历顺序:先遍历背包,再遍历物品
//        for (int i = 1; i <= bagWeight; i++){ // 遍历背包容量
//            for (int j = 0; j < weight.length; j++){ // 遍历物品
//                if (i - weight[j] >= 0){
//                    dp[i] = Math.max(dp[i], dp[i - weight[j]] + value[j]);
//                }
//            }
//        }
        //遍历顺序:先遍历物品,再遍历背包容量
        for (int i = 0; i < wLen; i++) {
            for (int j = 1; j <= bagWeight; j++) {//j从0和1都行 因为j=0结果肯定是0(默认值)
                if (j >= weight[i]) {
                    dp[j] = Math.max(dp[j], dp[j - weight[i]] + value[i]);
                }
            }
        }

        for (int i = 0; i <= bagWeight; i++) {
            System.out.println(dp[i]);
        }
    }

    @Test
    public void test2() {
        int[] weight = {1, 3, 4};//重量 2 3 4 5 9
        int[] value = {15, 20, 30};//价值3 4 5 8 10
        int bagWight = 4;
        testCompletePackAnotherWay(weight, value, bagWight);
    }

    //3有顺序的背包--LeetCode377
    //给你一个由 不同 整数组成的数组 nums ,和一个目标整数 target 。请你从 nums 中找出并返回总和为 target 的元素组合的个数。
    //情况1-顺序不同的组合当做相同的组合
    public int combinationSum41(int[] nums, int target) {
        int[] dp = new int[target + 1];
        dp[0] = 1;
        for (int i = 0; i < nums.length; i++) {
            for (int j = 1; j <= target; j++) {
                if (j >= nums[i]) {
                    dp[j] += dp[j - nums[i]];
                }
            }
        }
        for (int k = 0; k <= target; k++) {
            System.out.println(dp[k]);//1 1 2 3 4
        }
        return dp[target];
    }

    @Test
    public void test3() {
        int[] nums = {1, 2, 3};
        int target = 4;
        combinationSum41(nums, target);
    }

    //情况2-顺序相同的组合当做不同的组合
    public int combinationSum42(int[] nums, int target) {
        int[] dp = new int[target + 1];
        dp[0] = 1;
        for (int i = 0; i <= target; i++) {
            for (int j = 0; j < nums.length; j++) {
                if (i >= nums[j]) {
                    dp[i] += dp[i - nums[j]];//1 1 2 4 7
                }
            }
        }
        for (int k = 0; k <= target; k++) {
            System.out.println(dp[k]);
        }
        return dp[target];
    }

    @Test
    public void test4() {
        int[] nums = {1, 2, 3};
        int target = 4;
        combinationSum42(nums, target);
    }
}
posted @   fao99  阅读(295)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· DeepSeek 开源周回顾「GitHub 热点速览」
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
点击右上角即可分享
微信分享提示