多重背包问题和01背包问题

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/Hollake/article/details/98479028

多重背包问题相比01背包,限定了物品件数,求容量一定的情况下,价值最大

多重背包代码

import java.util.Scanner;


public class Main1 {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        while ( sc.hasNextInt() ) {
            int num = sc.nextInt();//总物品种类
            int money = sc.nextInt();//总钱数,也就是容量V
            int[] price = new int[num + 1];//价格,也就是权重wei
            int[] manyidu = new int[num + 1];//满意度,也就是价值val
            int[] cnt = new int[num + 1];//每个物品的个数cnt
            for (int i = 1; i <= num; i++) {
                price[i] = sc.nextInt();
                manyidu[i] = sc.nextInt();
                cnt[i] = sc.nextInt();
            }
            int maxManyidu = getMax(price, manyidu, cnt, num, money);
            System.out.println(maxManyidu);
        }
    }

    private static int getMax(int[] price, int[] manyidu, int[] cnt, int num, int money) {
        int[] V = new int[money + 1];//初始化价值的数组
        int cntNum = 0;//初始化所有种类的个数
        for (int i = 1; i <= num; i++) {//计算所有种类的数量,目的是转换为01背包问题
            cntNum += cnt[i];
        }
        int cur = 1;//标记进行到哪个物品了
        int sumCount = 0;//初始化当前进行到哪个位置的总和
        for (int i = 1; i <= cntNum; i++) {//循环所有物品的个数,也就是转换为01背包
            int oneMax = sumCount + cnt[cur];//按物品种类进行循环
            if (i > oneMax) {//判断当前是不是计算完当前物品的数量
                sumCount += cnt[cur];//每计算完当前的种类,那么就加上已经计算完的物品个数
                cur++;//移动到下一个物品
            }
//            转换为01背包,从大到小开始递减
            for (int j = money; j >= price[cur]; j--) {//只有在当前钱数或者容量大于这个物品价值的时候进行迭代
                /**
                 * 当前这个位置所对应的最大价值V[j],
                 * 当前位置的大小和当前的钱数-当前一个物品的价格所对应的最大价值,
                 * 再加上当前物品的价值,也就是当前物品花费所能提供的价值,V[j - price[cur]] + manyidu[cur]
                 * 比较这两个的最大值
                 */
                V[j] = Math.max(V[j], V[j - price[cur]] + manyidu[cur]);
            }
        }
        return V[money];
    }
}

测试案例

//3 100,表示3个种类的物品,总钱数为100
//26 100 4,依次表示为每件物品价格,价值,数量
//5 1 4
//5 2 2
//输出306
//3 21
//4 2 7
//9 11 2
//6 3 5
//22
//输出22

01背包问题

有n 种不同的物品,每个物品有两个属性,size 体积,value 价值,现在给一个容量为 w 的背包,问最多可带走多少价值的物品。也就是多重背包的个数限制为1.

import java.util.Scanner;

public class Bag01 {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        while ( sc.hasNextInt() ) {
            int n = sc.nextInt();//总物品种类
            int cp = sc.nextInt();//总容量cp
            int[] wei = new int[n + 1];//权重wei
            int[] val = new int[n + 1];//价值val
            for (int i = 1; i <= n; i++) {
                wei[i] = sc.nextInt();
                val[i] = sc.nextInt();
            }
            int maxVal = getMax01(cp, wei, val, n);
            System.out.println(maxVal);
        }
    }
    private static int getMax01(int cp, int[] wei, int[] val, int n) {
        int[] V = new int[cp + 1];
        for (int i = 1; i <= n; i++) {
            for (int j = cp; j >= wei[i]; j--) {
                V[j] = Math.max(V[j], V[j - wei[i]] + val[i]);
            }
        }
        return V[cp];
    }
}

测试代码

//4 8,物品个数,总容量
//2 3依次为权重,价值
//3 4
//4 5
//5 6
//10输出结果

完全背包相对于01背包和多重背包不限定数量,所以就是尽可能的装满。

而完全背包只需将第二层的循环变换一下即可

        for (int i = 1; i <= n; i++) {
            for (int j = wei[i]; j <= cp; j++) {
                V[j] = Math.max(V[j], V[j - wei[i]] + val[i]);
            }
        }

这篇文章写得很详细,可以直接看这一篇https://blog.csdn.net/yandaoqiusheng/article/details/84782655

 

猜你喜欢

转载自blog.csdn.net/Hollake/article/details/98479028