代码随想录算法训练营第四十二天| 背包问题

news2025/1/11 10:50:52

标准背包问题

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

举一个例子:

背包最大重量为4。

物品为:

重量价值
物品0115
物品1320
物品2430

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

  1. 确定dp数组以及下标的含义
    对于背包问题,有一种写法, 是使用二维数组,即
    dp[i][j] 表示从下标为[0-i]的物品里任意取,放进容量为j的背包,价值总和最大是多少

  2. 递推公式
     可以有两个方向推出来dp[i][j],

  • 不放物品i:由dp[i - 1][j]推出,即背包容量为j,里面不放物品i的最大价值,此时dp[i][j]就是dp[i - 1][j]。(其实就是当物品i的重量大于背包j的重量时,物品i无法放进背包中,所以背包内的价值依然和前面相同。)
  • 放物品i:由dp[i - 1][j - weight[i]]推出,dp[i - 1][j - weight[i]] 为背包容量为j - weight[i]的时候不放物品i的最大价值,那么dp[i - 1][j - weight[i]] + value[i] (物品i的价值),就是背包放物品i得到的最大价值

        所以递归公式: dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - weight[i]] + value[i]);
 

 3.dp数组初始化
        背包容量j为0的话,即dp[i][0],无论是选取哪些物品,背包价值总和一定为0。
        dp[0][j],即:i为0,存放编号0的物品的时候,各个容量的背包所能存放的最大价值。
        明显当 j < weight[0]的时候,dp[0][j] 应该是 0,因为背包容量比编号0的物品重量还小。
        当j >= weight[0]时,dp[0][j] 应该是value[0],因为背包容量放足够放编号0物品。

        其他下标应该初始化无所谓,因为根据递推公式看出:
        dp[i][j] 是由左上方数值推导出来了,故其他下标初始为什么数值都可以,因为都会被覆盖。

 4.确定遍历顺序
         有两个遍历的维度:物品与背包重量
          这里先遍历物品或遍历背包都可以
          递归公式中可以看出dp[i][j]是靠dp[i-1][j]和dp[i - 1][j - weight[i]]推导出来的。
          dp[i-1][j]和dp[i - 1][j - weight[i]] 都在dp[i][j]的左上角方向(包括正上方向)

先遍历物品,再遍历背包:

先遍历背包,再遍历物品:

5.举例推导dp数组

void test_2_wei_bag_problem1() {
    vector<int> weight = {1, 3, 4};
    vector<int> value = {15, 20, 30};
    int bagweight = 4;

    // 二维数组
    vector<vector<int>> dp(weight.size(), vector<int>(bagweight + 1, 0));

    // 初始化
    for (int j = weight[0]; j <= bagweight; j++) {
        dp[0][j] = value[0];
    }

    // weight数组的大小 就是物品个数
    for(int i = 1; i < weight.size(); i++) { // 遍历物品
        for(int j = 0; j <= bagweight; j++) { // 遍历背包容量
            if (j < weight[i]) dp[i][j] = dp[i - 1][j];
            else dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - weight[i]] + value[i]);

        }
    }

    cout << dp[weight.size() - 1][bagweight] << endl;
}

int main() {
    test_2_wei_bag_problem1();
}

滚动数组版背包问题

动规五部曲分析如下:

  1. 确定dp数组的定义
    dp[j]表示:容量为j的背包,所背的物品价值可以最大为dp[j]。
  2. 一维dp数组的递推公式
    dp[j] = max(dp[j], dp[j - weight[i]] + value[i]);
  3. dp数组初始化
    均初始化为0,因为dp可以被覆盖
  4. 一维dp数组遍历顺序
    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就会被重复加入多次!
    为什么二维dp数组历的时候不用倒序呢?
    因为对于二维dp,dp[i][j]都是通过上一层即dp[i - 1][j]计算而来,本层的dp[i][j]并不会被覆盖

  5. 举例推导dp数组
void test_1_wei_bag_problem() {
    vector<int> weight = {1, 3, 4};
    vector<int> value = {15, 20, 30};
    int bagWeight = 4;

    // 初始化
    vector<int> dp(bagWeight + 1, 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]);
        }
    }
    cout << dp[bagWeight] << endl;
}

int main() {
    test_1_wei_bag_problem();
}

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

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

相关文章

5.2.3目录与文件之权限意义

现在我们知道了Linux系统内文件的三种身份&#xff08;拥有者、群组与其他人&#xff09;&#xff0c;知道每种身份都有三种权限&#xff08;rwx&#xff09;&#xff0c; 已知道能够使用chown, chgrp, chmod去修改这些权限与属性&#xff0c;当然&#xff0c;利用ls -l去观察文…

《C++高级编程》读书笔记(十:揭秘继承技术)

1、参考引用 C高级编程&#xff08;第4版&#xff0c;C17标准&#xff09;马克葛瑞格尔 2、建议先看《21天学通C》 这本书入门&#xff0c;笔记链接如下 21天学通C读书笔记&#xff08;文章链接汇总&#xff09; 1. 使用继承构建类 1.1 扩展类 当使用 C 编写类定义时&#xf…

WMS中Choreographer 配合 VSYNC 中断信号

WMS中Choreographer 配合 VSYNC 中断信号 1、了解SurfaceFlinger中VSYNC信号刷新2、Choreographer 舞蹈编导2.1 Choreographer初始化2.2 FrameHandler中处理任务2.3 FrameDisplayEventReceiver初始化3.4 简易流程图 3、ViewRootImpl中scheduleTraversals3.1 postCallback 通过n…

java——IO与NIO

文章目录 1. 传统IO模型字节流字符流 2. NIO模型 Java中的IO&#xff08;输入输出&#xff09;是用于在程序中读取和写入数据的一种机制。Java提供了两种不同的IO模型&#xff1a;传统的IO模型和NIO&#xff08;New IO&#xff09;模型。 1. 传统IO模型 在传统的IO模型中&…

WPF本地化/国际化,多语言切换

之前写过winformwinform使用本地化&#xff0c;中英文切换_winform 中英文切换_故里2130的博客-CSDN博客 基本的技术差不多&#xff0c;但是后来又发现了一个ResXManager工具&#xff0c;可以更好方便快捷的使用。 首先下载&#xff0c;网络不好的话&#xff0c;去官网下载&a…

01背包简介

01背包问题&#xff08;0/1 Knapsack problem&#xff09;是一个经典的动态规划问题&#xff0c;它描述了在给定容量限制的情况下&#xff0c;如何选择一组物品放入背包&#xff0c;以使得物品的总价值最大化。 问题描述&#xff1a; 假设有一个背包&#xff0c;其容量为C。现…

VulnHub项目:Fawkes

1、靶机地址 HarryPotter: Fawkes ~ VulnHub 该篇为哈利波特死亡圣器系列最终部&#xff0c;也是最难的一个靶机&#xff0c;难度真的是逐步提升&#xff01;&#xff01;&#xff01; 2、渗透过程 确认靶机IP&#xff0c;kali IP&#xff0c;探测靶机开放端口 详细的扫描…

ICLR 23 | 工业视觉小样本异常检测最新网络:Graphcore

来源&#xff1a;投稿 作者&#xff1a;橡皮 编辑&#xff1a;学姐 论文链接&#xff1a;https://openreview.net/pdf?idxzmqxHdZAwO 论文代码&#xff1a;尚未开源 1.背景 随着人工智能中深度视觉检测技术的快速发展&#xff0c;检测工业产品表面的异常/缺陷受到了前所未有…

scratch lenet(11): C语言实现 squashing function

文章目录 1. 目的2. Sigmoidal Function2.1 S2 用到 Sigmoidal Function2.2 Sigmoidal Function 的定义 3. Squashing Function3.1 改用 Sigmoid Suahsing function 术语3.2 具体到 hyperlolic tangent 这一 squahsing function 4. Squahsing function 的实现References 1. 目的…

设计模式之观察者模式笔记

设计模式之观察者模式笔记 说明Observer(观察者)目录观察者模式示例类图抽象主题角色类抽象观察者类具体主题角色类具体的观察者角色类测试类 说明 记录下学习设计模式-观察者模式的写法。JDK使用版本为1.8版本。 Observer(观察者) 意图:定义对象间的一种一对多的依赖关系&a…

Gradle构建系统macOS安装与使用

1.打开gradle.org并点击安装 2.先决条件 ,确认安装JDK1.8或者更高版本已安装 在终端输入brew install gradle进行安装 安装成功如下: 查看安装版本号gradle -v 使用gradle 1.创建目录demo并进入该目录 mkdir demo cd demo 2.gradle init 使用Gradle开始构建 输入2开始构建应…

DevOps系列文章之 docker插件实现多实例部署(IDEA插件)

1. Docker的安装以及开启远程访问 1.1 安装 # 检查虚拟机内核版本&#xff0c;必须是3.10及以上 uname -r # 安装docker yum install docker # 输入y确认安装 # 启动docker systemctl start docker # 查看docker版本 docker -v # 开机启动docker systemctl enable docker # 停…

Golang学习日志 ━━ gin-vue-admin换机重新配置的记录,很愚蠢,很傻瓜,很机械...自己使用

最近一直在弄AI&#xff0c;没时间搞gva&#xff0c;所以有点忘记了&#xff0c;代码升级管它呢&#xff0c;全部重来一遍~ 一、备份保存 根据经验和个人喜好&#xff0c;我特别不喜欢在框架下把一个应用分散在module、api、service等等目录下&#xff0c;这种目录分配方案将把…

图上作业法

目录 交通示意图的表示方法 图上作业法 &#xff08;1&#xff09;对流 &#xff08;2&#xff09;迂回 物资调运问题的图上作业法 交通路线不成圈 交通路线成圈 交通示意图的表示方法 交通示意图是用来表明收发点的大致位置、收发量、交通路线长度的图形。 图形表示…

java mail发送、接收邮件

java mail接收邮件 1、引入java mail依赖 <dependency><groupId>org.eclipse.angus</groupId><artifactId>angus-mail</artifactId><version>2.0.2</version> </dependency>2、编写代码 注意&#xff1a;下述代码中的服务器…

从BNO055传感器获取IMU数据-2

在前面的文章 从BNO055传感器获取IMU数据-1 中介绍了BNO055传感器&#xff0c;今天继续讲解应用示例。 传感器与Arduino接口 我从某宝购买了固定在带有支持组件的开发板上的 BNO055 传感器。从 Digi-Key 或贸泽购买 BNO055 并将其焊接到 7.54.4mm 28 引脚 LGA 至 DIP 转换器上…

Groovy基础

Groovy基础 学Groovy有什么用&#xff1f;&#xff1f;&#xff1f;一、Groovy简介二、Mac安装Groovy1、使用homebrew安装或官网下载2、配置环境变量3、重新加载环境变量 二、Groov基本语法三、更多特性和扩展四、Groovy简单使用1、Groovy中的字符串及三大语句结构2、Groovy类与…

1带你入门MATLAB图像处理图像类型转换(附matlab程序)

1.简述 学习目标&#xff1a; 图像类型的转换 常用图像格式 图像格式&#xff1a;是存储图像采用的文件格式。不同的操作系统、不同的图像处理软件&#xff0c;所支持的图像格式都有可能不同。 在实际应用中经常会遇到的图像格式有&#xff1a;BMP、GIF、TIFF、PCX、JPEG、P…

FFmpeg5.0源码阅读——avformat_open_input

摘要&#xff1a;本文主要描述了FFmpeg中用于打开文件接口avformat_open_input的具体调用流程&#xff0c;详细描述了该接口被调用时所作的具体工作。   关键字&#xff1a;ffmpeg、avformat_open_input   注意&#xff1a;读者需要了解FFmpeg的基本使用流程&#xff0c;以…