背包问题(六)--分组背包

参考资料
背包九讲
https://www.acwing.com/activity/content/11/

分组背包模型

背包容量为V,有N组物品,每组物品只能选一件,第i组内的第j件物品容量cij,价值wij,求背包能放的最大价值

思路
f(i,v)表示从前i组物品选,体积小于等于v的最大价值
f(i,v) = max(f(i-1,v) , f(i-1,v-cij)+wij)
civ表示第i组的第j个物品的体积,wij表示第i组的第j个物品的价值

代码实现

import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int N = sc.nextInt();
        int V = sc.nextInt();
        int[][] v = new int[110][110];
        int[][] w = new int[110][110];
        int[] s = new int[110];

        for (int i = 1; i <= N; i++) {
            s[i] = sc.nextInt();
            for (int j = 0; j < s[i]; j++) {
                v[i][j] = sc.nextInt();
                w[i][j] = sc.nextInt();
            }
        }

        // 分组背包
        int[][] dp = new int[N + 1][V + 1];
        for (int i = 1; i <= N; i++) {
            for (int j = 1; j <= V; j++) {
                for (int k = 0; k < s[i]; k++) {
                    if(j<v[i][k]){
                        // 注意,这里不能直接写dp[i][j] = dp[i-1][[j]。我们要选的是当前组的最大值,而
                        // 不是选和不选当前商品的最大值
                        dp[i][j] = Math.max(dp[i][j],dp[i-1][j]);
                    } else {
                        // 此处同理,要选择当前组的最大值
                        dp[i][j] = Math.max(dp[i][j], 
                                        Math.max(dp[i-1][j],dp[i - 1][j - v[i][k]] + w[i][k]));
                    }
                }
            }
        }
        System.out.println(dp[N][V]);
    }
}

空间复杂度优化
滚动数组,二维数组降维到一维数组

import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int N = sc.nextInt();
        int V = sc.nextInt();
        int[][] v = new int[N+1][110];
        int[][] w = new int[N+1][110];
        int[] s = new int[N+1];

        for (int i = 1; i <= N; i++) {
            s[i] = sc.nextInt();
            for (int j = 0; j < s[i]; j++) {
                v[i][j] = sc.nextInt();
                w[i][j] = sc.nextInt();
            }
        }

        // 分组背包
        
        int[] dp = new int[V + 1];
        for (int i = 1; i <= N; i++) {
            for (int j = V; j >= 0; j--) {
                for (int k = 0; k < s[i]; k++) {
                    if (j >= v[i][k]) {
                        dp[j] = Math.max(dp[j], dp[j - v[i][k]] + w[i][k]);
                    }
                }
            }
        }
        System.out.println(dp[V]);
    }
}

全部评论

相关推荐

今天周一休息,突发奇想写一篇阶段总结。如题,我已经去了一个和Java彻底毫无关联的行业。曾经我以为自己能在计算机行业发光发热,没想到刚入行一年多就当了逃兵。从最开始的热爱到现在一看到代码就厌恶,不知道自己经历了什么。所以我去干什么了?答案是:在成都当了租房销售。上班那会压力大了就念叨着去干租房中介,但是一直下不去这个决心,想着自己学了四年多的计算机知识,终究还是不甘心。终于在某一天准备八股文的时候,看着无数篇和工作内容关系不大的理论知识,那一刻下定决心,决定尝试一下销售行业,也算是给自己一个交代。后面阴差阳错的投了成都自如去当租房管家,没想到面试很顺利,在当天一百多个面试的人里面,我成为了为数不多通过的几个幸运儿之一。目前已经培训通过,正式入职,也开了单,也有压力但是每天过得很开心,真心喜欢那种和人交流的感觉,哪怕是最后没有选择找我租房。说这些也是想告诉那些大三,大四正在找Java实习而焦虑的同学:你们现在还年轻,选择很多,容错率也很高,可以尽情去尝试自己喜欢的行业和工作。不用因为某一次的面试没通过或者简历石沉大海而焦虑,更不用因为身边人都在挤编程的独木桥就强迫自己跟风。也算是自己的碎碎念吧,也希望自己能在新的领域取得一点小成就。也祝牛油工作顺利!
沉淀小子:干啥都不丢人啊,生存是必须要的,销售很考验一个人综合素质能力的,好的销售人脉和资源可不比写字楼的白领差啊
点赞 评论 收藏
分享
评论
点赞
1
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务