01背包基础

01背包基础

问题

有n件物品和一个最多能背重量为w 的背包。第i件物品的重量是weight[i],得到的价值是value[i] 。每件物品只能用一次,求解将哪些物品装入背包里物品价值总和最大。
假设背包的最大重量为4
物品的信息如下

物品下标物品重量物品价值
0115
1320
2430

动态规划解决

对于背包问题,你先解决小背包(子背包)问题,再逐步解决原来的问题。
根据物品重量确定好划分背包大小的粒度
本问题中背包的最大容量为4,物品的重量依次是1,3,4
因此小背包的容量可以从零开始依次化为0,1,2,3,4
由此可以画出如下表格
在这里插入图片描述
dp[i][j]表示从物品下标为0到i物品中任选几件(每种物品只有一个)放入背包中,背包中的物品的最大价值。

接下来我们将依次将这个表格填写完整
对于第一行
我们只取物品0
当背包容量为零的时候显然什么也装不下,因此价值为0
当背包的容量为1,2,3,4时背包可以将物品零加入背包内价值为15
在这里插入图片描述

对于第二行
取物品时从物品0,物品1中选取
背包重量为0时价值为0
背包重量为1,2时,由于物品1的重量为3,背包依然装不下,所以背包还是只能装物品0,背包能装的物品的最大价值还是15
即dp[i][j]=dp[i-1][j]

当背包容量为3时,此时背包可以放下物品1了
但是背包要放物品1就不能放物品0,因此要分别考虑放物品1的情况和不放物品1的情况
不放物品1
就是背包重量为3,只放物品0的情况
既是dp[i][j]=dp[i-1][j]
放物品1
那我们要计算当前背包容量刨去放置物品1的容量后能装取的物品的最大价值
我们要记住,我们每填的一格都是在当前情况下的最优解决方案。所以上述的最大价值既是dp[i-1][j-物品1的重量](对于下标i-1,由于刨去了物品1的重量所以必然没有将物品1放入背包中)再加上物品一的价值。dp[i][j]=dp[i][j]=dp[i-1][j-物品1的重量]+物品1的价值
然后取这两个的最大值即

dp[i][j]=max( dp[i-1][j],dp[i-1][j-物品1的重量]+物品1的价值 )
这也是该问题的递推公式
在这里插入图片描述

对于第三行即物品2采取相同的策略
在这里插入图片描述

代码

    public static void main(String[] args) {
        int[] weight = {1, 3, 4};
        int[] value = {15, 20, 30};
        int bagsize = 4;
        testweightbagproblem(weight, value, bagsize);
    }

    public static void testweightbagproblem(int[] weight, int[] value, int bagsize){
        int wlen = weight.length, value0 = 0;
        //定义dp数组:dp[i][j]表示背包容量为j时,前i个物品能获得的最大价值
        int[][] dp = new int[wlen + 1][bagsize + 1];
        //初始化:背包容量为0时,能获得的价值都为0
        for (int i = 0; i <= wlen; i++){
            dp[i][0] = value0;
        }
        //遍历顺序:先遍历物品,再遍历背包容量
        for (int i = 1; i <= wlen; i++){
            for (int j = 1; j <= bagsize; j++){
                if (j < weight[i - 1]){
                    dp[i][j] = dp[i - 1][j];
                }else{
                    dp[i][j] = Math.max(dp[i - 1][j], dp[i - 1][j - weight[i - 1]] + value[i - 1]);
                }
            }
        }
        //打印dp数组
        for (int i = 0; i <= wlen; i++){
            for (int j = 0; j <= bagsize; j++){
                System.out.print(dp[i][j] + " ");
            }
            System.out.print("\n");
        }
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值