0-1背包问题

部分背包问题

部分背包求的是最大值,里面的物品可以分割,所以我们只需要求出物品的性价比,然后再排序就可以解决。

0-1背包问题

0-1背包,问题就在于你放还是不放。
假如我有三个物品:A(重:1,价值:2元)B(重:2,价值:4元)C(重:3,价值:3元)
然后我的背包只能承重 3. 那肯定是选 a和b了。因为 两个价值加起来有6元. 如果只放c,价值只有3元。
但是 我的背包能承重 5呢,ab还是6,但是bc就是7了,为了利益,所以要选择bc。
这就是0-1背包的痛点,因为要考虑重量是否符合背包。以及如何使价值最大化。

解决思路(动态规划)

我们假设 value 表示背包的总价值,k 表示放进去的物品的编号(这里我规定物品编号从1开始)。C 表示当前背包的当前的重量。
所以我们可以用一个共识来表示 value = B(k,C) 。B为一个函数,可以看作 将1到k的物品放入背包并且规定当前背包的容量,就可以得到他们当前最大的价值。
然后我们可以推断出。

包不够大

如果 第k个物品要放进去的时候,当前容量是C。C+K的重量>背包的重量那么:
B(k,C) = B(k-1,C)

包够

如果不大于则表示可以放入。
那么 则有两种情况,一个是放入,一个是不放入

包够大,且可以放入

放入那它的价值 value =B(k,C)=B(k-1,C-Ck) + Vk
注:Ck是K的重量,Vk是K的价值,C为当前背包容量
可能有疑惑的是:为什么要C-Ck,因为这种考虑是像K放入的时候,可能会将之前放入的几个物品或者全部物品排挤出去,但不能保证是否是可以保值的

包够大,但不放

那么 B(k,C) = B(k-1,C)

放与不放做比较,取最大值

所以在可以放的情况下,B(k,C) = max(B(k-1,C), B(k,C)=B(k-1,C-Ck) + Vk)
以上面的abc为例子:
横坐标是包的容量,从0开始到3 是背包的依次递增的容量

0123
00000
a(1)0222
b(2)0046
c(3)0046

java代码实现:

    public static int fun(int[] m, int[] v, int bagSize) {
        // m 和 v 都是从下标1开始
        int[][] B = new int[m.length + 1][bagSize + 1];
        int k = 1;
        for (; k <= m.length; k++) {
            for (int c = 1; c <= bagSize; c++) {
                // 超重了
                if (m[k - 1] + c > bagSize) {
                    B[k][c] = B[k - 1][c];
                }
                if (c >= m[k - 1]) {
                    B[k][c] = Integer.max(B[k - 1][c], B[k - 1][c - m[k - 1]] + v[k - 1]);
                }
            }
        }
        for (int i = 0; i <= m.length; i++) {
            for (int j = 0; j < bagSize + 1; j++) {
                System.out.printf("%3d",B[i][j]);
            }
            System.out.print("\n");
        }
        return B[m.length][bagSize];
    }

    public static void main(String[] args) {
        int[] m = {1, 2, 3};
        int[] v = {2, 4, 3};
        int bagSize = 3;
        int fun = fun(m, v, bagSize);
        System.out.println(fun);
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值