代码随想录刷题| 多重背包理论基础、背包问题的总结

简介: 代码随想录刷题| 多重背包理论基础、背包问题的总结

多重背包理论基础

多重背包的问题

  • 有N种物品和一个容量为V 的背包。第i种物品最多有Mi件可用,每件耗费的空间是Ci ,价值是Wi 。求解将哪些物品装入背包可使这些物品的耗费的空间 总和不超过背包容量,且价值总和最大

多重背包的解法


  • 多重背包问题可以使用01背包的思路去解决
  • 既然物品的数量是固定,就可以使用01背包,只不过其中的物品有重复
  • 假设现在有个背包如下:

33091904585f44138c4f7403152ce064.png

  • 可以将这个多重背包转换成:

6c60b44a85234228926a325c0da23db4.png

  • 这就可以看成一个01背包问题了


多重背包的代码

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class MultiBagProblem {
    public static void main(String[] args) {
        // 物品信息
        /**
         *          重量  价值  数值
         *  物品0     1    15    2
         *  物品1     3    20    3
         *  物品2     4    20    2
         */
        List<Integer> weight = new ArrayList<>(Arrays.asList(1,3,4));
        List<Integer> value = new ArrayList<>(Arrays.asList(15,20,30));
        List<Integer> nums = new ArrayList<>(Arrays.asList(2,3,3));
        // 背包信息
        int bagSize = 10;
        multiBag(weight,value,nums,bagSize);
    }
    /**
     *
     * @param weight  物品的重量
     * @param value   物品的价值
     * @param nums    物品的数量
     * @param bagSize 背包的容量
     */
    private static void multiBag(List<Integer> weight,
                          List<Integer> value,
                          List<Integer> nums,
                          int bagSize) {
        /**
         * 将物品展开
         */
        // 先把物品展开,展开成一个物品只有一个
        for (int i = 0; i < nums.size(); i++) {
            while (nums.get(i) > 1) {
                weight.add(weight.get(i));
                value.add(value.get(i));
                nums.set(i , nums.get(i) - 1);   // 展开一个,原数量就减一
            }
        }
        /**
         * 按照01背包进行装包
         */
        // 创建dp数组
        int[] dp = new int[bagSize+1];
        // 遍历更新dp数组
        for (int i = 0; i < weight.size(); i++) {  // 先对物品进行遍历
            for (int j = bagSize; j >= weight.get(i); j--) {  // 再对背包进行倒序遍历
                dp[j] = Math.max(dp[j],dp[j-weight.get(i)] + value.get(i));
            }
            // 打印dp数组
            System.out.println("物品" + i + "\t" + Arrays.toString(dp));
        }
    }
}


背包问题的总结

01背包


01背包是重中之重

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

主要有以下几种问题:

1、求物品装进背包中的最大价值(纯01背包)

递推公式原理为:dp[ j ] = max( dp[ j ] , dp[ j - weight[ i ] ] + value[ i ]);

对应的题目

416.分割等和子集

1049.最后一块石头的重量||

2、求物品装满背包的方法数

递推公式原理为:dp[ j ] += dp[ j - weight[ i ] ]

由于方法数是逐步积累的,所以初始化应该是dp[ 0 ] = 1

对应的题目

494.目标和

3、求最终背包中的物品数

递推公式原理为:dp[ j - weight[ i ] + 1]

如果是求最大个数:就是dp[ j ] = max(dp[ j ],dp[ j - weight[ i ] ] + 1 );由于是求最大值,初始化时dp[0] = 0,其余的也为0。对应的题目有 474.一和零

如果是求最小个数:就是dp[ j ] = min(dp[ j ],dp[ j - weight[ i ] ] + 1 );由于是求最小值,初始化时dp[0] = 0,其余的为MAX_VALUE。对应的题目有 322.零钱兑换


完全背包


01背包的时候,为了使物品在向背包中添加的时候保证物品只添加一次,在遍历背包的时候使用倒序遍历

那完全背包中的物品是可以被重复添加的,那么在遍历背包的时候使用正序遍历,就可以保证物品被多次添加

主要有以下几种问题

1、求物品装进背包中的最大价值(纯完全背包)

递推公式原理为:dp[ j ] = max( dp[ j ] , dp[ j - weight[ i ] ] + value[ i ]);

2、求物品装满背包的方法数

递推公式原理为:dp[ j ] += dp[ j - weight[ i ] ]

由于方法数是逐步积累的,所以初始化应该是dp[ 0 ] = 1

对应的题目

518.零钱兑换|| —— 求组合数 —— 先遍历物品再遍历背包

377.组合总和IV —— 求排列数 —— 先遍历背包再遍历物品

70.爬楼梯 —— 求排列数 —— 先遍历背包再遍历物品

3、求最终背包中的物品数

递推公式原理为:dp[ j - weight[ i ] + 1]

如果是求最小个数:就是dp[ j ] = min(dp[ j ],dp[ j - weight[ i ] ] + 1 );由于是求最小值,初始化时dp[0] = 0,其余的为MAX_VALUE

对应的题目

322.零钱兑换

279.完全平方数


多重背包

  • 多重背包的解决方案就是将多重背包转换成01背包进行处理
  • 原理上并没有什么难点,等遇到相应的题目再说


相关文章
|
算法
【AcWing算法基础课】第五章 动态规划(未完待续)(3)
当然,一个人能够滑动到某相邻区域的前提是该区域的高度低于自己目前所在区域的高度。
112 0
牛客刷题之数学基础-快速幂
牛客刷题之数学基础-快速幂
61 0
|
7月前
|
存储 算法 Java
六六力扣刷题数组之理论基础
六六力扣刷题数组之理论基础
80 0
|
Python
牛客刷题之数学基础-约数
牛客刷题之数学基础-约数
57 0
|
算法
代码随想录Day20 回溯算法 LeetCode77 组合问题
代码随想录Day20 回溯算法 LeetCode77 组合问题
39 0
[算法刷题题解笔记] 洛谷 P1007 独木桥 [贪心]
[算法刷题题解笔记] 洛谷 P1007 独木桥 [贪心]
|
算法 Android开发
LeetCode 周赛上分之旅 #34 按部就班地解决动态规划问题
学习数据结构与算法的关键在于掌握问题背后的算法思维框架,你的思考越抽象,它能覆盖的问题域就越广,理解难度也更复杂。在这个专栏里,小彭与你分享每场 LeetCode 周赛的解题报告,一起体会上分之旅。
74 0
牛客网《剑指offer》专栏刷题练习之掌握动态规划思想
牛客网《剑指offer》专栏刷题练习之掌握动态规划思想
130 0
代码随想录刷题| 01背包理论基础 LeetCode 416. 分割等和子集
代码随想录刷题| 01背包理论基础 LeetCode 416. 分割等和子集
代码随想录刷题| 01背包理论基础 LeetCode 416. 分割等和子集
|
存储 算法 编译器
代码随想录刷题|动态规划理论基础 LeetCode 509. 斐波那契数 70. 爬楼梯 746. 使用最小花费爬楼梯(上)
代码随想录刷题|动态规划理论基础 LeetCode 509. 斐波那契数 70. 爬楼梯 746. 使用最小花费爬楼梯
代码随想录刷题|动态规划理论基础 LeetCode 509. 斐波那契数 70. 爬楼梯 746. 使用最小花费爬楼梯(上)