解密01背包问题:如何在有限空间中实现最大价值?

news2024/9/19 10:40:15

文章目录

  • 01背包 - 问题分析
  • 01背包题目
    • 第一问
      • 1. 状态表示
      • 2. 分析状态转移方程
      • 3. 初始化
      • 4. 填表顺序
      • 5. 返回值
    • 第二问
      • 1. 状态表示
      • 2. 状态转移⽅程
      • 3. 初始化
      • 4. 填表顺序
      • 5. 返回值
  • C++运行代码

01背包 - 问题分析

01背包是指在一个有容积限制(或者重量限制)的背包中放入物品,物品拥有体积、重量和价值等属性。需要求一种满足背包限制的放置物品的方式,使得背包中物品的价值之和最大。比如有n件物品和一个最多能背重量为w 的背包。第i件物品的重量是weight[i],得到的价值是value[i] 。每件物品只能用一次,求解将哪些物品装入背包里物品价值总和最大。

在这里插入图片描述

在01背包问题中,每种物品仅有一件,可以选择放或不放。这是背包问题中最简单的一种,也是动态规划的经典问题之一。


  • 在下面的讲解中,我举一个例子:

背包最大重量为5.
物品为:
在这里插入图片描述

  • 问背包能背的物品最大价值是多少?

此时发现物品1 + 物品3 的重量为3 价值为14。 此时这是我们最大价值

  • 若背包恰好装满,求至多能装多大价值的物品是多少?

此时发现物品1 + 物品3 的重量为3 价值为14. 但是重量没有恰好装满,不符合题意.
我们在看物品2 + 物品3 的重量为5,价值为9. 重量恰好装满,且是我们这里的最大价值


01背包题目

【模板】01背包_牛客题霸_牛客网 (nowcoder.com)

动规五部曲分析:

  1. 分析状态表示
  2. 分析状态转移方程
  3. 初始化
  4. 填表顺序
  5. 返回值

第一问

  • 问背包能背的物品最大价值是多少

1. 状态表示

我们看看这个状态表示

dp[i] 表示: 从前 i 个物品中选,所有选法中,能挑选出来的最大价值.

相信很多同学第一时间是想出的是这个状态表示,但你们仔细想一下,我们的体积呢?这个状态表示体积可能会超出题目给定的范围,所有这个状态表示是错.我们必须换一种状态表示,我们换一个二维的数组,加多一维表示体积.

dp[i][j] 表⽰:从前 i 个物品中挑选,总体积「不超过J」 ,所有的选法中,能挑选出来的最⼤价值。

v表示体积,w表示价值

要时刻记着这个dp数组的含义,下面的一些步骤都围绕这dp数组的含义进行的,如果哪里看懵了,就来回顾一下i代表什么,j又代表什么。


2. 分析状态转移方程

  • 线性 dp 状态转移⽅程分析⽅式,⼀般都是根据「最后⼀步」的状况,来分情况讨论:
  1. 如果不放第i个物品的值

最后⼀步如果不选第 i 个物品.相当于就是去前 i - 1 个物品中挑选,并且总体积不超过 j
其实就是当物品i的重量大于背包j的重量时,物品i无法放进背包中,所以背包内的价值依然和前面相同。

  1. 如果选择第i个物品

那么我就只能去前 i - 1 个物品中,挑选总体积不超过 j - v[i]的物品,。此时 dp[i][j] = dp[i - 1][j - v[i]] + w[i] 。因此需要特判⼀下 j >= v[i],因为要留⾜够的体积装这个第 i 个物品。综上,状态转移⽅程为: dp[i][j] = max(dp[i 1][j], dp[i - 1][j - v[i]] +w[i])

如果没看懂回顾一下状态表示, dp[i][j] 表⽰:从前 i 个物品中挑选,总体积「不超过J」 ,所有的选法中,能挑选出来的最⼤价值。

综上,状态转移⽅程为:
dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - v[i]] + w[i]) ,但需要特判一下 dp[i - 1][j - v[i]] + w[i])` 是否存在.


3. 初始化

  • 初始化的意义就是让我填表时候不越界,需要我们需要对边界条件处理一下.

我们多加⼀⾏,⽅便我们的初始化
在这里插入图片描述

  1. 第一个位置

i 是物品 ,从 0 号位置开始选,但是没有 0 号位置,因为物品是从 1 到 n的,所有填 0。

  1. 第一行

从 0 号位置开始选,容量不超过 0,此时仅需将第⼀⾏初始化为 0 即可。因为什么也不选,也能满⾜体积不⼩于 j 的情况,此时的价值为 0 。

在这里插入图片描述

  1. 我们讨论第 0 竖的情况,讨论 j,容量不超过 0,物品总是有体积,所以全部都不
    选,初始化成 0.
    在这里插入图片描述

4. 填表顺序

根据「状态转移⽅程」,我们仅需「从上往下」填表即可。


5. 返回值

我们看看状态转移⽅程
从前 i 个物品中挑选,最⼤价值总体积不超过 j,所有的选法中,能挑选出来的最⼤价值。根据「状态表⽰」,返回 dp[n][V] 。


第二问

  • 若背包恰好装满,求至多能装多大价值的物品是多少?

其实第⼆问仅需微调⼀下 dp 过程的五步即可。


1. 状态表示

还是跟之前一样

dp[i][j] 表⽰:从前 i 个物品中挑选,总体积正好等于 j ,所有的选法中,能挑选出来的最⼤价值。


2. 状态转移⽅程

  • 线性 dp 状态转移⽅程分析⽅式,⼀般都是根据「最后⼀步」的状况,来分情况讨论:

我们的dp[i-1][j]不一定存在 , 因为有可能凑不⻬ j 体积的物品,因此我们把不合法的状态设置为 -1 。不能等于0,因为0是代表没有物品选.

  • 其实分析情况跟第一问差不多,但是要注意细节
  1. 如果不放第i个物品的值

最后一步如果不选第i个物品.相当于就是去前 i - 1 个物品中挑选此时, 这个无需判断是否是-1,因为在dp[i][j]这种情况是一定存在的,所有我们的dp[i][j]可以先等于dp[i-1][j] .如果dp[i-1][j]是等于-1的话,那没关系,你选不了我也选不了,你从i-1个物品想凑成一个j,我这种情况也凑不成j,所有不用判断 dp[i][j] = dp[i -1][ j ]

  1. 如果选择第i个物品

在使⽤ dp[i][j - v[i]] 的时候,不仅要判断 j >= v[i] ,⼜要判断 dp[i][j -
v[i]] 表⽰的情况是否合法,也就是 dp[i][j - v[i]] != -1

综上,状态转移⽅程为:
dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - v[i]] + w[i]) ,但是在使⽤ dp[i - 1][j - v[i]] 的时候,要判断 j >= v[i] ,因为要留⾜够的体积装这个第 i 个物品。,⼜要判断 dp[i - 1][j - v[i]] 表⽰的情况是否合法,也就是 dp[i - 1][j - v[i]] != -1


3. 初始化

  • 初始化的意义就是让我填表时候不越界,需要我们需要对边界条件处理一下.

跟之前一样我们多加⼀⾏,⽅便我们的初始化
在这里插入图片描述

  1. 第一个位置

跟之前一样第一个物品是0的位置,容量为0,正好不选就可以了,所有初始化成0.
在这里插入图片描述

  1. 第一行

没有物品想凑成容量为1-n 那是不可能的,因为没有物品哪里的体积,那就是非法的,所有填-1
在这里插入图片描述

  1. 我们讨论第 0 竖的情况, 这个状态可以根据状态转移方程推导而出,当然判断条件j ≥ v[i] 为false不会进去

4. 填表顺序

根据状态转移⽅程,我们仅需从上往下填表即可。


5. 返回值

我们看看状态转移⽅程
从前 i 个物品中挑选,最⼤价值总体积不超过 j,所有的选法中,能挑选出来的最⼤价值。根据「状态表⽰」,返回 dp[n][V] 。但是由于最后可能凑不成体积为 V 的情况,因此返回之前需要「特判」⼀下。


C++运行代码

#include <iostream>
#include <string.h>
using namespace std;

const int N = 1010;
int n, V, v[N], w[N];
int dp[N][N];
int main()
{
    // 读⼊数据
    cin >> n >> V;
    for (int i = 1; i <= n; i++)
        cin >> v[i] >> w[i];

    // 解决第⼀问
    for (int i = 1; i <= n; i++)
        for (int j = 0; j <= V; j++) // 修改遍历顺序
        {
            dp[i][j] = dp[i - 1][j];
            if (j >= v[i])
                dp[i][j] = max(dp[i][j], dp[i - 1][j - v[i]] + w[i]);
        }

    cout << dp[n][V] << endl;


    // 解决第⼆问
    memset(dp, 0, sizeof dp);
    for (int j = 1; j <= V; j++) dp[0][j] = -1; //初始化


    for (int i = 1; i <= n; i++)
        for (int j = 0; j <= V; j++) // 修改遍历顺序
        {
            dp[i][j] = dp[i - 1][j];
            if (j >= v[i] && dp[i - 1][j - v[i]] != -1)
                dp[i][j] = max(dp[i][j], dp[i - 1][j - v[i]] + w[i]);
        }

    //由于最后可能凑不成体积为 V 的情况,因此返回之前需要特判⼀下。
    cout << (dp[n][V] == -1 ? 0 : dp[n][V]) << endl;
    return 0;
}

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

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

相关文章

了解消息中间件的基础知识

为什么要使用消息中间件&#xff1f; 解耦&#xff1a;消息中间件可以使不同的应用程序通过解耦的方式进行通信&#xff0c;减少系统间的依赖关系提供异步通信&#xff1a;消息中间件可以实现异步消息传递&#xff0c;提高系统的响应性能。流量削峰&#xff1a;消息中间件可以…

vue项目实现table表格竖向

先上图 思路&#xff1a;使用element ui 自带的栅格&#xff0c;通过控制el-col 的span 属性来设置每行展示多少行&#xff08;竖着的字段&#xff09;&#xff0c;超过就自动换行&#xff1b; content1 是表头 content2是返回的数据 getTable()函数是将返回的正常数据进行处理…

SQL12 高级操作符练习(2)

描述 题目&#xff1a;现在运营想要找到学校为北大或GPA在3.7以上(不包括3.7)的用户进行调研&#xff0c;请你取出相关数据&#xff08;使用OR实现&#xff09; 示例&#xff1a;user_profile iddevice_idgenderageuniversitygpa12138male21北京大学3.423214male复旦大学4.03…

【SpringMVC】工作流程入门案例的使用

目录 一、什么是SpringMVC 二、SpringMVC的请求流程 三、SpringMVC的优点 四、Spring MVC的主要组件 五、SpringMVC常用注解 六、入门案例演示 6.1.添加pom.xml 6.2.创建spring-mvc.xml 6.3.配置web.xml 6.4.SpringMVC配置Web 6.5.JSP页面编写 七、扩展 7.1.Spring…

全科医学科常用评估量表汇总,建议收藏!

根据全科医学科医生的量表使用情况&#xff0c;笔者整理了10个常用的全科医学科量表&#xff0c;可在线评测直接出结果&#xff0c;可转发使用&#xff0c;可生成二维码使用&#xff0c;可创建项目进行数据管理&#xff0c;有需要的小伙伴赶紧收藏&#xff01; 日常生活能力量表…

HarmonyOS Codelab 优秀样例——溪村小镇(ArkTS)

一、介绍 溪村小镇是一款展示溪流背坡村园区风貌的应用&#xff0c;包括园区内的导航功能&#xff0c;小火车行车状态查看&#xff0c;以及各区域的风景展览介绍&#xff0c;主要用于展示HarmonyOS的ArkUI能力和动画效果。具体包括如下功能&#xff1a; 打开应用时进入启动页&a…

白灯和黄灯哪个对眼睛好?那些专家推荐的护眼灯

随着电子产品普及&#xff0c;虽然给我们生活带来了很多便利&#xff0c;不过也因此有不少人用眼过度导致近视。尤其是孩子&#xff0c;如今不少小孩小小年纪就戴上了眼镜&#xff0c;究其原因&#xff0c;除了繁重的课业还有户外运动的缺失、环境光照的不足、用眼卫生和习惯的…

SpringMVC系列(一)之SpringMVC入门详细介绍

一. SpringMVC简介 Spring MVC是一个基于Java的实现了MVC设计模式的请求驱动类型的轻量级Web框架&#xff0c;通过把Model&#xff0c;View&#xff0c;Controller分离&#xff0c;将web层进行职责解耦&#xff0c;把复杂的web应用分成逻辑清晰的几部分&#xff0c;简化开发&a…

Android Studio的笔记--aidl实现和调用

android AIDL接口使用 aidl实现新建aidl实现工程build.gradleproguard-rules.pro增加aidl文件 增加aidl实现aidl实现服务打开aidl服务 aidl使用新建aidl使用工程增加aidl文件使用aidl方法 相关回显 aidl实现 新建aidl实现工程 新建一个工程。工程名testaidl。包名com.lxh.tes…

第 3 章 栈和队列 (使用线性链表和队列实现银行业务模拟)

1. 背景说明 该模拟业务基于时间线来确定&#xff0c;当事件发生时&#xff0c;通过插入升序链表来模拟时间线记录事件发生时间、类型&#xff0c;类似于记事本&#xff0c;由于 时间是单向的&#xff0c;正好符合队列的先进先出特性&#xff0c;类似于我们生活中的排队行为。…

小程序类找茬游戏开发:创造富有挑战性和娱乐性的游戏体验

小程序找茬游戏是一种受欢迎的益智娱乐游戏&#xff0c;玩家需要在两幅几乎相同的图片中找出差异。这种类型的游戏结合了观察力和注意力&#xff0c;提供了有趣的挑战。在本文中&#xff0c;我们将讨论如何开发小程序找茬游戏&#xff0c;以及关键特点和开发流程。 小程序找茬…

初露头角!Walrus入选服贸会“数智影响力”数字化转型创新案例

9月5日&#xff0c;由北京市通信管理局、工业和信息化部新闻宣传中心联合主办的“企业数字化转型论坛”在2023中国国际服务贸易交易会期间召开&#xff0c;论坛以“数字化引领 高质量发展”主题&#xff0c;旨在探讨信息技术如何与各行业深度融合&#xff0c;构建数字化转型新格…

C++vector模拟实现

vector模拟实现 1.构造函数2.拷贝构造3.析构赋值运算符重载4.iterator5.modifiers5.1push_back5.2pop_back5.3empty5.4insert5.5erase5.6swap 6.Capacity6.1size6.2capacity6.3reserve6.4resize6.5empty 7.Element access7.1operator[]7.2at 8.在谈reserve vector官方库实现的是…

SpringBoot整合Redis,基于Jedis实现redis各种操作

前言&#xff08;三步教你学会redis&#xff0c;主打一个实用&#xff09; springboot整合redis步骤&#xff0c;并基于jedis对redis数据库进行相关操作&#xff0c;最后分享非常好用、功能非常全的redis工具类。 第一步&#xff1a;导入maven依赖 <!-- springboot整合re…

C++之智能指针shared_ptr死锁问题(二百)

简介&#xff1a; CSDN博客专家&#xff0c;专注Android/Linux系统&#xff0c;分享多mic语音方案、音视频、编解码等技术&#xff0c;与大家一起成长&#xff01; 优质专栏&#xff1a;Audio工程师进阶系列【原创干货持续更新中……】&#x1f680; 人生格言&#xff1a; 人生…

Hadoop生态圈中的Flume数据日志采集工具

Hadoop生态圈中的Flume数据日志采集工具 一、数据采集的问题二、数据采集一般使用的技术三、扩展&#xff1a;通过爬虫技术采集第三方网站数据四、Flume日志采集工具概述五、Flume采集数据的时候&#xff0c;核心是编写Flume的采集脚本xxx.conf六、Flume案例实操1、采集一个网络…

卫星地图-航拍影像-叠加配准套合(ArcGIS版)

卫星地图-航拍影像-叠加配准套合(ArcGIS版) 发布时间&#xff1a;2018-01-17 版权&#xff1a;BIGEMAP 第一步 工具准备 BIGEMAP地图下载器&#xff1a;Bigemap系列产品-GIS行业基础软件kml\shp 相关教程&#xff1a;CAD文件直接导入BIGEMAP进行套合配准&#xff08;推荐&am…

苹果笔不用原装可以吗?苹果ipad触控笔推荐

很多小伙伴在纠结&#xff0c;是否要购买apple pencil呢&#xff1f;但它的价格太过昂贵&#xff0c;很多学生党都消费不起。答案是不一定的要入手apple pencil的。市面上也是有做得相当不错的平替电容笔。现在无纸化已经快成为我们生活中的一部分&#xff0c;它不仅是可以书写…

新网站怎么优化才能提升排名-彻底解决新网站没收录和排名的问题

新网站怎么优化才能提升排名&#xff1f;辛辛苦苦搭建起网站后&#xff0c;却不知如何优化网站提升排名&#xff0c;也没有一个完整的思路和策略&#xff0c;今天做为行业资深SEO的我&#xff0c;来为大家理清SEO思路&#xff0c;彻底解决新网站没收录和排名的问题&#xff01;…

网站不收录没排名降权怎么处理-紧急措施可恢复网站

网站降权对于SEO人员来说是非常致命的打击&#xff0c;因为网站一旦被搜索引擎降权&#xff0c;排名会严重地下降&#xff0c;网站的流量也会大幅下降&#xff0c;直接影响到收益。而且处理不好的话会导致恢复的时间周期无限拉长&#xff0c;所以网站被降权后我们要第一时间采取…