【动态规划】01背包问题(滚动数组 + 手画图解)

news2024/12/25 2:43:47

        01背包除了可以用形象的二维动态数组表示外,还可以使用空间复杂度更低的一维滚动数组。

目录

文章目录

前言

一、滚动数组的基本理解

二、确定dp及其下标含义

三、确定递推公式

四、确定初始化

五、确定遍历顺序

1.用物品(正序)遍历背包(正序)

实现代码:

手写图解: 

2.用背包(正序)遍历物品(正序)

实现代码:

手写图解: 

3.用物品(正序)遍历背包(逆序)

实现代码:

手写图解: ​编辑

总结



前言

        晦涩难懂的滚动数组,有两个非常重要的点:①倒序②物品嵌套背包遍历


一、滚动数组的基本理解

        我对于滚动数组的理解是:

        滚动数组是基于二维数组之上产生的,之所以滚动数组能够用一维的方式去完成和二维同样的工作,原因就是在于这个滚动数组能够重复产生数据,进而有“滚动”的效果。

        滚动数组的本质还是二维数组,只是数据不再产生新的行,只在一行上一直进行数据的覆盖更新,因此要特别注意数据污染的情况。

二、确定dp及其下标含义

        由题意与我们将要创建的一维数组可知,dp[j]的含义是:背包容量为j时能装的最大价值。

三、确定递推公式

        与二维dp数组相同,dp[j]的状态可以由两种状态得来:

        ①拿第i件物品(拿了以后,背包容量会减,价值会增加);

        ②不拿第i件物品;

        所以可得:dp[j] = max(dp[j], dp[j - weight[i]] + value[i]);


四、确定初始化

        由递推公式可得:dp[j]是由它之前的数据得来的,也即想要知道dp[j]的数值,就需要知道dp[j-x]的数据。(x是往前推的、未定的下标)

        所以初始化只需要初始化dp[0]为0即可。(目前分析来说)

五、确定遍历顺序

        与二维数组相同的是,一维dp数组仍然需要遍历物品和背包容量两种变量,只有这样才能模拟出将物品放入背包的过程。

1.用物品(正序)遍历背包(正序)

实现代码:

for (int j = 0; j < bagCapacity; j++)
    {
        for (int i = 0; i < weight.size(); i++)
        {
            // 背包容量够放
            if (j >= weight[i])
            {
                dp[j] = max(dp[j], dp[j - weight[i]] + value[i]);
            }
            // 不够放
            else
            {
                dp[j] = dp[j];
            }
        }
    }

手写图解: 

         由此我们可以很明显地看出在一维dp数组的情况下,数据覆盖的时候会发生污染,发现了物品0被放进dp[2]两次。

        难道是遍历前后顺序不对?

2.用背包(正序)遍历物品(正序)

实现代码:

for (int i = 0; i < weight.size(); i++)
        {
            for (int j = 0; j < bagCapacity; j++)
            {
            // 背包容量够放
            if (j >= weight[i])
            {
                dp[j] = max(dp[j], dp[j - weight[i]] + value[i]);
            }
            // 不够放
            else
            {
                dp[j] = dp[j];
            }
        }

手写图解: 

        交换后,还是不可避免地发生了数据污染。

        由此我们可以知道:

        正序遍历的时候会将上一个物品装进背包两回,导致错误,而逆序就可保证dp[j]不受前面数据的影响(这时前面的数据仍然都是0),也就保证了每件物品只被放进去一次。

        分析到这,我们也可以知道:初始化必须让整个dp数组的值都初始化为0(后面的dp[j]不能受前面数据的影响)。

3.用物品(正序)遍历背包(逆序)

实现代码:

for (int i = 0; i < weight.size(); i++)
    {
        for (int j = bagCapacity; j >= 0; j--)
        {
            // 背包容量够放
            if (j >= weight[i])
            {
                dp[j] = max(dp[j], dp[j - weight[i]] + value[i]);
            }
            // 不够放
            else
            {
                dp[j] = dp[j];
            }
        }
    }

手写图解: 

总结

        最后我也验证了,既然遍历背包容量的时候需要倒序,那么可不可以再将倒序的背包和正序的物品颠倒位置?

运行结果:

        原因是:从后向前遍历背包容量,见到能放进去的物品就跟已经已经在背包里的价值相比较,选择大的,但是这样一来不会发生价值的相加,只是看哪个物品价值高,并且在背包容量范围内,那就放进背包成为dp[j]。

        遍历顺序在较复杂的dp题中是非常重要的一环。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/337232.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【刷题篇】链表(上)

前言&#x1f308;前段时间我们学习了单向链表和双向链表&#xff0c;本期将带来3道与链表相关的OJ题来巩固对链表的理解。话不多说&#xff0c;让我们进入今天的题目吧&#xff01;&#x1f680;本期的题目有&#xff1a;反转单链表、链表的中间结点、合并两个有序链表反转单链…

XCP实战系列介绍09-基于Vehicle Spy进行XCP测量步骤详解

本文框架 1.概述2. 基于SPY进行测量步骤2.1 建立ECU和vspy3通信2.2 DAQ数据设置2.3 测量变量的记录2.3.1 需要记录变量的选择2.3.2 Log保存3. 在MEP中观测变量3.1 添加观测变量3.2 实时更新变量的值1.概述 在介绍了ASAP2 Editor进行A2l文件的生成,及如何使用Vehicle Spy进行X…

点云深度学习系列博客(五): Point Transformer方法概述

在上一篇博客《注意力机制原理概述》中&#xff0c;我们介绍了注意力机制的基本原理以及一些技术细节。基于注意力机制的深度学习模型在起初设计时&#xff0c;针对的是NLP问题。包括词元分析&#xff0c;翻译等语言处理任务&#xff0c;注意力机制能够训练超大规模数据&#x…

活动星投票午间修身自习室制作在线投票投票制作网页

“午间修身自习室”网络评选投票_免费小程序投票推广_小程序投票平台好处手机互联网给所有人都带来不同程度的便利&#xff0c;而微信已经成为国民的系统级别的应用。现在很多人都会在微信群或朋友圈里转发投票&#xff0c;对于运营及推广来说找一个合适的投票小程序能够提高工…

SpringBoot整合(三)SpringBoot发送邮件

使用SpringBoot发送邮件 邮件发送其实是一个非常常见的需求&#xff0c;用户注册&#xff0c;找回密码等地方&#xff0c;都会用到&#xff0c;Spring Boot 中对于邮件发送&#xff0c;提供了相关的自动化配置类&#xff0c;使得邮件发送变得非常容易。 1、前置工作 目前国内…

[SSD固态硬盘技术 9] FTL详解

了解硬件特性有助于我们针对特性进行进一步的探索与优化。为了使闪存成为存储数据的友好介质&#xff0c;我们需要一种机制&#xff1a;将更新的信息写入新的空页&#xff0c;然后将 所有后续读取请求转移到其新地址确保新编程的页面均匀分布在所有可用闪存中&#xff0c;以便均…

【Python入门第五天】Python 变量

创建变量 变量是存放数据值的容器。 与其他编程语言不同&#xff0c;Python 没有声明变量的命令。 首次为其赋值时&#xff0c;才会创建变量。 实例 x 10 y "Bill" print(x) print(y)运行实例 变量不需要使用任何特定类型声明&#xff0c;甚至可以在设置后更改…

Jupyter 使用Anaconda 虚拟环境内核

Anaconda 虚拟环境中使用Jupyter Notebook 安装好Anaconda之后&#xff0c;进入Anaconda Prompt&#xff0c;创建虚拟环境&#xff0c;env_name是创建的环境的名字。 conda creat -n env_name python3.9等虚拟环境搭建好之后&#xff0c;激活环境。 conda activate env_name…

网络流与图(一)

线性规划问题是运筹学最基本的问题&#xff0c;我们已经学过不少的解决方法&#xff0c;今天继续学习针对线性规划问题的另一种高效算法——网络流问题&#xff08;network flow problem&#xff09;1网络流模型为了更好介绍该算法来龙去脉&#xff0c;与以往一样&#xff0c;从…

MongoDB 删除文档

MongoDB 删除文档 MongoDB remove() 、deleteMany()、deleteOne()函数是用来移除集合中的数据。 remove()删除文档 remove() 方法的基本语法格式如下所示&#xff1a; db.collection.remove(<query>,<justOne> ) 如果你的 MongoDB 是 2.6 版本以后的&#xff0c…

filter及backdrop-filter属性详解

filter属性详解 filter 属性定义了元素(通常是<img>)的可视效果(例如&#xff1a;模糊与饱和度)。 filter: none | blur() | brightness() | contrast() | drop-shadow() | grayscale() | hue-rotate() | invert() | opacity() | saturate() | sepia() | url();下面运用…

聚观早报 |字节开展类ChatGPT研究;特斯拉前AI负责人将加入OpenAI

今日要闻&#xff1a;字节开展类ChatGPT研究&#xff1b;丰田汽车第三财季净利润同比下降8.1% 特斯拉前AI负责人将加入OpenAI&#xff1b;快手&#xff1a;正在开展大规模语言模型研究&#xff1b;劳斯莱斯CEO称客户希望更多电动汽车 字节开展类ChatGPT研究 北京时间 2 月 9 日…

零代码做分析报表的bi软件才是好软件

有些数据分析软件对IT的依赖比较重&#xff0c;在制作报表的过程中需要用到SQL&#xff0c;这就导致了IT人员懂技术不懂业务&#xff0c;业务人员懂业务不懂技术&#xff0c;数据分析做来做去总是差点什么的局面。要是遇到了IT部门相对较弱的情况&#xff0c;还会加重IT负担&am…

字符串函数能有什么坏心思?

&#x1f680;write in front&#x1f680; &#x1f4dd;个人主页&#xff1a;认真写博客的夏目浅石. &#x1f381;欢迎各位→点赞&#x1f44d; 收藏⭐️ 留言&#x1f4dd; &#x1f4e3;系列专栏&#xff1a;夏目的C语言宝藏 &#x1f4ac;总结&#xff1a;希望你看完之…

又发现一个ChatGPT国内镜像站,无次数限制也无广告

ChatGPT 美国OpenAI研发的聊天机器人程序&#xff0c;于2022年11月30日发布。ChatGPT是人工智能技术驱动的自然语言处理工具&#xff0c;它能够通过学习和理解人类的语言来进行对话&#xff0c;还能根据聊天的上下文进行互动&#xff0c;真正像人类一样来聊天交流&#xff0c;…

传统目标检测实战:Sift/ORB+Match

传统目标检测实战&#xff1a;Sift/ORBMatch 文章目录传统目标检测实战&#xff1a;Sift/ORBMatch1. 前言2. 先验知识3. 项目框架4. 工具函数&#xff08;utils.py&#xff09;5. 检测待测图像&#xff08;test_xxxx.py&#xff09;5.1 使用图像缩放金字塔&#xff08;test_PG.…

大数据技术架构(组件)31——Spark:Optimize--->JVM On Compute

2.1.9.4、Optimize--->JVM On Compute首要的一个问题就是GC,那么先来了解下其原理&#xff1a;1、内存管理其实就是对象的管理&#xff0c;包括对象的分配和释放&#xff0c;如果显式的释放对象&#xff0c;只要把该对象赋值为null&#xff0c;即该对象变为不可达.GC将负责回…

ISYSTEM调试实践9-winIDEA Analyzer功能2

上一篇文章介绍了如何启动Trace,并配置。本文简单介绍一下Analyzer的输出结果&#xff0c;具体每个窗口的内容。 1、程序溯源 Profiler Timeline介绍了函数在时间轴上的执行调用情况。鼠标左键可以设置具体时间点&#xff0c;CTRL 左键和CTRL 右键设置观测的时间窗口&#xf…

技术树基础——16排它平方数(Bigdecimal,int,string,数组的转换)

题目&#xff1a;03879 * 203879 41566646641这有什么神奇呢&#xff1f;仔细观察&#xff0c;203879 是个6位数&#xff0c;并且它的每个数位上的数字都是不同的&#xff0c;并且它平方后的所有数位上都不出现组成它自身的数字。具有这样特点的6位数还有一个&#xff0c;请你…

openFeign源码学习

openFeign这个框架要解决的问题是&#xff1a;通常在调用远程接口的时候&#xff0c;如果是http请求&#xff0c;需要我们通过restTemplate去拼接调用参数和连接&#xff0c;然后发起调用&#xff0c;openFeign帮我们把拼接参数的这个过程包装了起来&#xff0c;通过代理对象的…