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

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

多重背包理论基础

多重背包的问题

  • 有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背包进行处理
  • 原理上并没有什么难点,等遇到相应的题目再说


相关文章
|
自然语言处理 安全 C++
【C++ 格式化输出 】C++20 现代C++格式化:拥抱std--format简化你的代码
【C++ 格式化输出 】C++20 现代C++格式化:拥抱std--format简化你的代码
10077 4
|
5月前
|
IDE 开发工具 Python
通义灵码+支付 MCP:30 分钟实现创作打赏智能体
本文介绍如何使用通义灵码智能体与 qwen3 和支付 MCP 编写创作打赏智能体,该智能体能够完成日常聊天、诗词创作和请求打赏并生成支付链接功能。
532 0
|
6月前
|
Shell 测试技术 API
Claude Code 官方内部团队最佳实践!
Immerse,独立开发者、内容创作者、AGI实践者,分享编程、AI、开源等内容。关注公众号“沉浸式趣谈”及个人网站获取更新。欢迎点赞、评论、转发支持!本文介绍Claude Code——智能编程命令行工具及其使用技巧。
4500 0
|
人工智能 架构师 自动驾驶
期待已久,真正的 AI 程序员来了
6 月 21 日,在阿里云上海 AI 峰会上,阿里云推出首个“AI 程序员”,它具备架构师、开发工程师、测试工程师等多种岗位的技能,能一站式自主完成任务分解、代码编写、测试、问题修复、代码提交整个过程,最快分钟级即可完成应用开发,大幅提升研发效率。
1848 110
|
Java Nacos Docker
微服务入门教程
微服务入门教程
321 2
|
消息中间件 存储 NoSQL
剖析 Redis List 消息队列的三种消费线程模型
Redis 列表(List)是一种简单的字符串列表,它的底层实现是一个双向链表。 生产环境,很多公司都将 Redis 列表应用于轻量级消息队列 。这篇文章,我们聊聊如何使用 List 命令实现消息队列的功能以及剖析消费者线程模型 。
剖析 Redis List 消息队列的三种消费线程模型
|
算法 Java
什么是EL表达式
EL表达式,全称为Expression Language,意为表达式语言。它是Servlet规范中的一部分,也是JSP2.0规范加入的内容。EL表达式的主要作用是用于在Java Web应用中访问和操作数据,使得JSP页面能够摆脱Java代码块和JSP表达式,实现代码的简化。
602 3
|
机器学习/深度学习 人工智能 自然语言处理
【AI大模型】Transformers大模型库(二):AutoModelForCausalLM
【AI大模型】Transformers大模型库(二):AutoModelForCausalLM
818 1
|
机器学习/深度学习 自然语言处理 PyTorch
Transformers入门指南:从零开始理解Transformer模型
【10月更文挑战第29天】作为一名机器学习爱好者,我深知在自然语言处理(NLP)领域,Transformer模型的重要性。自从2017年Google的研究团队提出Transformer以来,它迅速成为NLP领域的主流模型,广泛应用于机器翻译、文本生成、情感分析等多个任务。本文旨在为初学者提供一个全面的Transformers入门指南,介绍Transformer模型的基本概念、结构组成及其相对于传统RNN和CNN模型的优势。
13338 1
|
存储 运维 小程序
后端开发零负担!揭秘支付宝小程序云开发的高效与安全,你的项目也能飞速上线?
【8月更文挑战第27天】支付宝小程序云开发是由阿里云提供的集成开发环境,助力开发者高效、安全地构建小程序后端服务,免去服务器搭建,显著提高开发效率并降低运维成本。它集成了云函数、云数据库及云存储等功能,便于快速搭建后端逻辑。例如,仅需简单几行代码即可创建HTTP接口或进行数据管理。这使得开发者能更专注于业务逻辑和用户体验优化,同时平台还提供了强大的安全保障措施,确保数据安全和用户隐私。无论对于初创团队还是成熟企业,支付宝小程序云开发都能有效提升产品迭代速度和市场竞争力。
425 1

热门文章

最新文章