动态规划之01背包

news2025/6/7 10:53:38

首要

由于自己的个人原因(说白了就是懒),忙于各种事情,实在忙不过来(哭),只能把发文分享的事情一推再推,直到某天良心发现产生了想发文的想法,于是就写下了这篇文章,请各位大佬轻喷

背包问题

 背包问题是一种经典的dp了,有01背包,完全背包,多重背包和分组背包

我们今天讲的01背包就是最初始最基础的模型

概念讲述

假设我们现在有一个容量为bagweight的背包,有n件物品可以被我们携带,而这n件物品各有他们的价值v和重量w,求当背包装了i件物品时的最大价值,每件物品只能被带一次

假设

物品0,重量1,价值10

物品1,重量3,价值20

物品2,重量4,价值25

背包容量为4

我当时看见这种题目第一时间想的是是否可以暴力求解,但貌似会超时

于是回归到主线,动态规划

这种题目属于动态规划中的背包问题,并且是最为基础的01背包问题

在写动态规划问题时,最好将动态规划五部曲再回想一遍

dp数组及其下标的含义-------->非常重要,其他几项都是围绕着这一项进行展开

dp数组的递推式--------->建议:可以随便举出例子,然后试着找到影响这个例子的子问题或者因素

dp数组的初始化-------->就是找出不用任何条件就可以得出结论的数据

确定dp数组的遍历顺序--------->从前向后还是从后向前遍历?

dp数组打印日志检查----------->debug的好办法

这里涉及到了许多信息,背包容量限制,物品数量限制,这些限制也会是我们进行数据筛选的条件

dp数组及其下标的含义

每个物品只有两种状态,一是拿取,二是不拿

这里采用二维dp数组,dp[i][j],这分别代表了两个维度:物品和背包容量

i代表物品,j代表背包容量

dp[0][0]就是:现背包容量为0的情况下,对于物品0的处理,当然,只有拿和不拿

由于背包容量为0,那么说明只有不拿这种情况,dp[0][0]=0,同理,当j为0时,dp[i][0]的i不管取何值都会使其变为0,即此时最大价值只能为0

dp数组递推式

我们先随便取出一个数组元素dp[2][3],这说明背包容量为3时,在下标0到2之间选择物品得到的最大价值是多少

对于物品2,我们可以进行考虑选还是不选,

如果选,那么我们就要腾出物品2的空间进行存放物品2,然后背包容量变为了0,此时转到了dp[1][0],即背包容量为0的情况下,在下标0和1的商品之间进行拿取,得到的最大价值是多少,dp[1][0]=0,所以得出此时的背包价值为25,注意:此时代表的不是最大价值,只是背包的某种情况下的价值

 如果不选,那么我们就要在下标0和1中进行选择即dp[1][3],但这个dp[1][3]我们已经求出结果,此时只需要将其与上面得出的值进行比较得出最大即可

最后得出递推式dp[ i ][ j ]=max(dp[ i - 1 ][ j - weight[ i ] ]+value[ i ],dp[ i -1 ][ j ])//前者代表选择,后者代表没选

由于已经经过选择,那么就需要将下标进行移动,在下标0到i-1中再次进行选择吧

dp数组初始化

上面已经讲到:当背包容量为0时,此时的最大价值就一定是0,dp[i][0]=0

然后根据递推式可以知道,i由i-1推导得出,这是从前往后推导得出,那么就需要知道i=0时的情况

当j<weight[0]时,即此时的背包容量不足以装载物品0,此时的最大值也就是0

当j>=weight[0]时,dp[0][j]=weight[0],因为此时背包只能从下标0中进行选择,并且此时背包已经可以装下物品0,那么为了最大起见,就要选择将物品0装入背包

剩下的部分初始化为我们在得到的结果中绝对不可能出现的值,如果出现了可能出现的值,那么不能确定此时的值是已经更改过的值还是原本就有的值

dp数组的遍历顺序

遍历顺序从背包重量过来和物品过来都可以

背包问题的状态都可以进行压缩实现

滚动数组的实现条件:上一层可以重复利用,可以直接拷贝到当前层

dp数组一维滚动数组实现

 首先,我们知道根据上文dp[i][j]=max(dp[i-1][j-weight[i]]+value[i],dp[i-1][j]);

我们可以知道i都是从i-1过来的,那么直接从i-1这里进行拷贝即可

dp[i][j]=max(dp[i][j-weight[i]]+value[i],dp[i][j])

此时我们可以很直观的感受到,这个dp数组是一层套着一层逐级移动,一遍又一遍的覆盖,那还用什么二维数组,直接一维数组即可解决

dp[j]=max(dp[j-weight[i]]+value[i],dp[j])

这样我们的dp数组就变成了一维状态

dp[i][j]表示的是在下标0到i之间,背包容量为j时得到的最大价值

现在是dp[j],背包容量为j的情况下所得到的最大价值

一维滚动数组初始化

当j为0时,容量为0不能存东西,dp[0]=0

其他下标所对应元素直接初始化为0即可

如果对初始化没有思路时,请直接看向递推式,千万不要凭感觉就往上写

一维数组的遍历方式(很重要(其实每个步骤都很重要!))

特别注意! 

注意这里的遍历是倒序进行书写

for(int i = 0; i < weight.size(); i++) { // 遍历物品
    for(int j = bagWeight; j >= weight[i]; j--) { // 遍历背包容量
        dp[j] = max(dp[j], dp[j - weight[i]] + value[i]);

    }
}
//此处代码转载自代码随想录

变化更慢的是先遍历的变量

先遍历物品后遍历背包容量 

如果正序进行书写,就会出现以下情况

此时i=0,j=1

dp[1]=max(dp[1],dp[1-weight[0]]+value[0])

dp[1]经过初始化后为0,得dp[1]=15

dp[2]=max(dp[2],dp[2-weight[0]]+value[0])

dp[2]经过初始化后为0,dp[2]=30  ???

出现问题了,我们将weight[0]重复计算了一遍!

由于在遍历背包容量的过程中,我们的物品尚未被改变,那么只要后面的容量大于weight[0],我们便会将当前的dp[i]从后往前迭代一个value[0],从而引发错误

所以我们需要倒序书写

假设bagweight=4

此时i=0,j=4

dp[4]=max(dp[4],dp[4-weight[0]]+value[0])

此时dp[4]经过初始化后为0,dp[4]=dp[3]+value[0]=15

dp[3]=max(dp[3],dp[3-weight[0]]+value[0])

dp[3]=15

这样取得的状态不会与之前重叠,顺利完成遍历

思考,我们是否可以先遍历背包容量再遍历物品

这是不可以的

上面说了dp[j]代表了背包容量为j的情况下,能够得到的最大价值

如果我们先遍历背包容量,那么我们的背包容量就是从大到小的过程,此时背包中只会放入一个物品

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

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

相关文章

灵活控制,modbus tcp转ethernetip的 多功能水处理方案

油田自动化和先进的油气行业软件为油气公司带来了诸多益处。其中包括&#xff1a; 1.自动化可以消除多余的步骤、减少人为错误并降低运行设备所需的能量&#xff0c;从而降低成本。 2.油天然气行业不断追求高水平生产。自动化可以更轻松地减少计划外停机时间&#xff0c;从而…

深入了解linux系统—— 进程池

前言&#xff1a; 本篇博客所涉及到的代码以同步到本人gitee&#xff1a;进程池 迟来的grown/linux - 码云 - 开源中国 一、池化技术 在之前的学习中&#xff0c;多多少少都听说过池&#xff0c;例如内存池&#xff0c;线程池等等。 那这些池到底是干什么的呢&#xff1f;池…

光电耦合器:数字时代的隐形守护者

在数字化、自动化高速发展的今天&#xff0c;光电耦合器正以一种低调却不可或缺的方式&#xff0c;悄然改变着我们的生活。它不仅是电子电路中的“安全卫士”&#xff0c;更是连接信号世界的“桥梁”&#xff0c;凭借出色的电气隔离能力&#xff0c;为各类设备提供稳定可靠的信…

手机如何防止ip关联?3种低成本方案

在当今数字化时代&#xff0c;手机已成为人们日常生活中不可或缺的工具&#xff0c;无论是社交、购物、支付还是工作&#xff0c;都离不开手机。然而&#xff0c;随着网络技术的不断发展&#xff0c;网络安全问题也日益突出&#xff0c;其中IP关联问题尤为常见。那么&#xff0…

Pandas和Django的示例Demo

以下是一个结合Pandas和Django的示例Demo&#xff0c;展示如何在Django项目中读取、处理和展示Pandas数据。 Pandas和Django的示例Demo 前置条件&#xff1a; 安装python 基础设置 确保已安装Django和Pandas&#xff1a; pip install django pandasInstalling collected p…

【p2p、分布式,区块链笔记 MESH】Bluetooth蓝牙通信拓扑与操作 BR/EDR(经典蓝牙)和 BLE

目录 1. BR/EDR&#xff08;经典蓝牙&#xff09;网络结构微微网&#xff08;Piconet&#xff09;散射网&#xff08;Scatternet&#xff09;蓝牙 BR/EDR 拓扑结构示意图 2. BLE&#xff08;低功耗蓝牙&#xff09;网络结构广播器与观察者&#xff08;Broadcaster and Observer…

航道无人机巡检系统

随着长江干线、京杭运河等航道智慧化升级提速&#xff0c;传统人工巡检模式已难以满足高频次、大范围、高精度的航道管理需求。无人机凭借其灵活机动、多源感知、高效覆盖等优势&#xff0c;正成为航道巡检的“空中卫士”。本文将结合多地成功案例&#xff0c;从选型标准、技术…

【JVM】Java虚拟机(一)——内存结构

目录 一、简介 二、程序计数器 三、虚拟机栈 栈帧结构&#xff1a; 特点&#xff1a; 四、本地方法栈 特点&#xff1a; 五、堆 堆结构&#xff1a; 特点&#xff1a; 对象分配过程&#xff1a; 六、方法区 方法区结构&#xff1a; 特点&#xff1a; 运行时常量池…

从微积分到集合论(1630-1910)(历史简介)——第4章——现代积分理论的起源(Thomas Hawkins)

第 4 章 现代积分理论的起源 (The Origins of Modern Theories of Integration) Thomas Hawkins 目录 4.1 引言(Introduction) 4.2 Fourier分析与任意函数(Fourier analysis and arbitrary functions) 4.3 对Fourier问题的回应(Responses to Fourier)(1821-1854)…

《Linux运维总结:宝德服务器RAID开启(方式一)》

总结&#xff1a;整理不易&#xff0c;如果对你有帮助&#xff0c;可否点赞关注一下&#xff1f; 更多详细内容请参考&#xff1a;Linux运维实战总结 一、背景信息 说明&#xff1a;从客户那里退回来的一台宝德服务器&#xff0c;硬盘不见了&#xff0c;现在需要用两个2T的硬盘…

NY118NY120美光固态闪存NY124NY129

NY118NY120美光固态闪存NY124NY129 美光NY系列固态闪存深度解析&#xff1a;技术、性能与行业洞察 技术架构与核心创新 美光NY系列&#xff08;包括NY118、NY120、NY124、NY129等型号&#xff09;作为企业级存储解决方案的代表作&#xff0c;延续了品牌在3D NAND技术上的深厚…

Odoo 19 路线图(新功能)

Odoo 19 路线图(新功能) Odoo 19 路线图是Odoo官方针对下一版本的发布计划&#xff0c;将在自动化、合规性、用户体验、碳排放报告及本地化等领域推出超过16项新功能。本路线图详细阐述了Odoo 19如何在过往版本基础上进一步提升&#xff0c;助力企业优化销售、财务、运营及客户…

基于NXP例程学习CAN UDS刷写流程

文章目录 前言1.概述1.1 诊断报文 2.协议数据单元(N_PDU)2.1 寻址信息&#xff08;N_AI&#xff09;2.1.1 物理寻址2.1.2 功能寻址2.1.3 常规寻址&#xff08;Normal addressing&#xff09;2.1.4 常规固定寻址&#xff08;Normal fixed addressing&#xff09;2.1.5 扩展寻址&…

基于有效集MPC控制算法的直线同步电机simulink建模与仿真,MPC使用S函数实现

目录 1.课题概述 2.系统仿真结果 3.核心程序 4.系统仿真参数 5.系统原理简介 6.参考文献 7.完整工程文件 1.课题概述 有效集算法通过迭代地选择一组 "有效" 约束&#xff0c;将约束优化问题转化为一系列无约束或等式约束优化问题。直线同步电机 (Linear Synch…

让敏感数据在流转与存储中始终守护在安全范围

在企业数字化运营浪潮中&#xff0c;企业内部应用服务器面临着非法访问、数据泄露等风险&#xff0c;如何全面守护应用服务器文件安全&#xff0c;让敏感数据在流转与存储中始终守护在安全范围&#xff1f; 服务器白名单让数据流转安全又高效 天 锐 蓝盾的服务器白名单功能既…

【Linux】find 命令详解及使用示例:递归查找文件和目录

【Linux】find 命令详解及使用示例&#xff1a;递归查找文件和目录 引言 find 是 Linux/Unix 系统中强大的文件搜索工具&#xff0c;用于在目录层次结构中递归查找文件和目录。它提供了丰富的搜索条件和灵活的操作选项&#xff0c;可以满足从简单到复杂的各种文件查找需求。 …

【论文阅读笔记】万花筒:用于异构多智能体强化学习的可学习掩码

摘要 在多智能体强化学习&#xff08;MARL&#xff09;中&#xff0c;通常采用参数共享来提高样本效率。然而&#xff0c;全参数共享的流行方法通常会导致智能体之间的策略同质&#xff0c;这可能会限制从策略多样性中获得的性能优势。为了解决这一关键限制&#xff0c;我们提出…

负载均衡LB》》HAproxy

Ubuntu 22.04 安装HA-proxy 官网 资料 # 更新系统包列表&#xff1a; sudo apt update # 安装 HAproxy sudo apt install haproxy -y # 验证安装 haproxy -v # 如下图配置 Haproxy 在这里插入代码片》》》配置完之后 重启 Haproxy sudo systemctl restart haproxy 补充几…

UE 5 和simulink联合仿真,如果先在UE5这一端结束Play,过一段时间以后**Unreal Engine 5** 中会出现显存不足错误

提问 UE5报错如图。解析原因 回答 你遇到的这个错误提示是&#xff1a; “Out of video memory trying to allocate a rendering resource. Make sure your video card has the minimum required memory, try lowering the resolution and/or closing other applications tha…

Rust 控制流

文章目录 Rust 控制流if 表达式循环实现重复用 loop 重复代码从循环返回值循环标签用于区分多层循环while 条件循环用 for 循环遍历集合 Rust 控制流 在大多数编程语言中&#xff0c;根据条件是否为真来运行某些代码&#xff0c;以及在条件为真时重复运行某些代码&#xff0c;是…