【动态规划】0-1背包问题

news2025/2/27 14:24:49

概述

0-1背包问题是一种经典的动态规划问题,它的基本形式是:有一个背包,容量为 C C C,有 n n n 个物品 i i i,每个物品 i i i 的重量为 w i w_i wi,价值为 v i v_i vi。现在要从这 n n n 个物品中选出若干个放入背包中,使得背包中物品的总重量不超过 C C C,且物品的总价值最大。

解题思路

这个问题可以用动态规划来解决,一般使用一个二维数组 d p dp dp 来存储最大价值。

d p [ i ] [ j ] dp[i][j] dp[i][j] 表示在前 i i i 个物品中选择若干个物品,恰好放入容量为 j j j 的背包中,可以获得的最大价值。

那么对于每个物品,我们可以选择将其放入背包中,也可以选择不放入。

如果选择将第 i i i 个物品放入背包中,则有 d p [ i ] [ j ] = d p [ i − 1 ] [ j − w i ] + v i dp[i][j] = dp[i-1][j-w_i] + v_i dp[i][j]=dp[i1][jwi]+vi

如果选择不放入,则有 d p [ i ] [ j ] = d p [ i − 1 ] [ j ] dp[i][j] = dp[i-1][j] dp[i][j]=dp[i1][j]。我们需要取这两种情况的较大值作为 d p [ i ] [ j ] dp[i][j] dp[i][j] 的值。

可以得到状态转移方程如下:

dp[i][j]=max⁡(dp[i−1][j−wi]+vi,dp[i−1][j])

最后,最大价值就是 d p [ n ] [ C ] dp[n][C] dp[n][C]

图表分析

书包重量(公斤)012345678
物品不存在000000000
物品1:6公斤、48元000000484848
物品2:1公斤、7元077777484848
物品3:5公斤、40元0777740485555
物品4:2公斤、12元0712191940485560
物品5:1公斤、8元0815202740485663

当物品不存在和书包重量为0的时候,背包价值肯定也为0。

切记:dp[i][j]表示前i个物品、背包承重为j时的最大价值。

前一件物品:只有当背包容量为6的时空才可以装下,所以dp[1][6]=48。由于这是选择的前一件物品,那么在背包容量为7和8时,不会考虑后面的物品,值还是48。

前两件物品:当背包容量为1时,可以装下第二件物品,这时背包价值为7,dp[2][1] = 7。一直到书包承重5公斤时,都只能装下物品2,dp[2][1]到dp[2][5]都是等于7。 书包承重6公斤时,可以装物品1或物品2,两者只能装1个,通过对比物品1和物品2的价值大小,我们选择物品1,即dp[2][6]=48。书包承重7公斤时,可以同时装物品1、物品2,此时dp[2][7]=物品2的价值 + 物品1的价值=55。dp[2][8]也是同样的道理。

前三件物品:背包容量从1到4时,只能装下物品2,即最大价值为7。当背包容量为5时,可以装下物品3,价值为40,当背包容量为6时,只装物品1,背包价值为48。

以此类推,可得到五件物品的情况下,背包能装下且得到的最大价值是多少。

示例代码

#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

int knapsack(vector<int>& weights, vector<int>& values, int capacity) {
    int n = weights.size();
    vector<vector<int>> dp(n + 1, vector<int>(capacity + 1, 0));

    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= capacity; j++) {
            if (weights[i - 1] > j) {
                // 当前物品重量大于背包容量,无法放入,继承上一个最优解
                dp[i][j] = dp[i - 1][j];
            } else {
                // 当前物品可以选择放入或者不放入
                dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - weights[i - 1]] + values[i - 1]);
            }
        }
    }

    return dp[n][capacity];
}

int main() {
	vector<int> weights = { 6, 1, 5, 2, 1 };
	vector<int> values = { 48, 7, 40, 12, 8 };
    int capacity = 8;

    int result = knapsack(weights, values, capacity);
    cout << "Max value: " << result << endl;

    return 0;
}

运行结果如下所示:
在这里插入图片描述

解析:
首先定义了函数knapsack,该函数接受三个参数:物品重量的数组weights、物品价值的数组values和背包容量capacity。函数返回值为能够装入背包的最大价值。

函数内部,首先获取物品的数量n,然后定义了一个dp数组来保存中间计算结果。其中,dp[i][j]表示前i个物品,容量为j时,能够获得的最大价值。

接下来使用两层循环,遍历每一个可能的状态。对于每个状态,如果当前物品重量大于背包容量,则无法放入背包中,继承上一个最优解。否则,当前物品可以选择放入或者不放入背包中。这里使用了max函数来求解当前状态下的最大值。最后返回dp[n][capacity]即可。

在main函数中,定义了物品重量、价值和背包容量的数组,并调用knapsack函数求解最大价值,并输出结果。

总结

0-1背包问题是一个经典的动态规划问题,求解的是一个有限容量的背包所能携带的最大价值。其特点是:每种物品只有一个,可以选择装或不装,不能部分装入。

0-1背包问题可以用动态规划来解决。具体思路如下:

  1. 定义状态:定义 dp[i][j] 表示前 i 个物品放入容量为 j 的背包中所能获得的最大价值。

  2. 初始化状态:dp[0][j] 和 dp[i][0] 都初始化为 0,因为当没有物品或者背包容量为 0 时,所能获得的最大价值为 0。

  3. 状态转移方程:当当前物品重量大于当前背包容量时,无法放入,当前最优解为继承上一个最优解;否则,当前物品可以选择放入或者不放入,取决于两种情况下的最大价值。dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - weights[i - 1]] + values[i - 1]);

  4. 返回结果:dp[n][capacity] 表示前 n 个物品放入容量为 capacity 的背包中所能获得的最大价值。

代码实现时,可以使用二维数组 dp[i][j] 来存储状态转移方程的结果,其中 i 表示物品的编号,j 表示背包的容量。初始化时,将 dp[0][j] 和 dp[i][0] 都初始化为 0。最终结果为 dp[n][capacity]。时间复杂度为 O(ncapacity),空间复杂度为 O(ncapacity)。

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

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

相关文章

id选择器和class选择器

id选择器 id选择器用来选取带有给定id属性的元素。语法:#id例如: html <div id"container">...</div>css #container {color: blue; }id选择器的一些特征: 1. id选择器以#号开头,后跟元素的id属性值。 2. id选择器只能选取带有给定id属性的元素。 3.…

在 Windows 上安装 kubectl

一、前言 个人主页: ζ小菜鸡大家好我是ζ小菜鸡&#xff0c;让我们一起学习在 Windows 上安装 kubectl。如果文章对你有帮助、欢迎关注、点赞、收藏(一键三连) 二、 kubectl是什么 kubectl是Kubernetes集群的命令行工具&#xff0c;通过kubectl能够对集群本身进行管理&#xf…

一篇文章学会高级IO

文章目录 理解IO的本质认识五种IO模型阻塞式IO非阻塞式IO信号驱动式IO多路转接式IO异步式IO 高级IO的理解以及意义多路转接式IO的深入学习select模型select函数详解封装网络套接字&#xff1a;Sock.hppselectServer.cc(服务器文件)运行结果小结 poll模型poll函数详解Sock.hpppo…

Reed-Muller序列

Reed-Muller函数的由来 我们知道对于连续信号&#xff0c;时间和频率是对偶域(duality)&#xff0c;其中正弦函数是时移的特征函数&#xff08;where sinusoids are eigenfunctions of time shifts&#xff09;。而在汉明空间(Hamming space)中&#xff0c;there are discrete…

牛客网面试必刷:BM19 寻找峰值

牛客网面试必刷&#xff1a;BM19 寻找峰值 前言一、解法1&#xff1a;暴力依次搜索二、解法2&#xff1a;二分搜索 前言 给定一个长度为n的数组nums&#xff0c;请你找到峰值并返回其索引。数组可能包含多个峰值&#xff0c;在这种情况下&#xff0c;返回任何一个所在位置即可…

数据库基础篇 -- 1

目录 数据库基础 1.1&#xff1a;什么是数据库 1.2&#xff1a;常见数据库 1.3&#xff1a;数据库的基本使用 1.4&#xff1a;mysql的架构 1.5&#xff1a;sql分类 1.6&#xff1a;存储引擎 数据库基础 1.1&#xff1a;什么是数据库 数据库是指存储和管理结构化数据的…

解决频繁操作svn导致提交文件失败svn: E155015,亲测成功

我是因为频繁在本地删除创建重复的包和.java文件&#xff0c;以至于在提交至svn的时候会出现我之前删除的包和.java文件&#xff0c;所以我致力于将其删除干净&#xff0c;频繁的在本地删除、去svn删除…以至于再后来本地项目中和svn中都没有但是还是svn: E155015&#xff0c;查…

Cesium入门之五:认识Cesium中的Viewer

Viewer是Cesium中用于显示3D场景的组件。它提供了创建和控制3D场景所需的所有基本功能&#xff0c;包括加载3D模型、添加图像覆盖物、设置相机位置和方向、处理用户输入等。 在创建Viewer时&#xff0c;可以指定要使用的HTML元素&#xff08;例如canvas&#xff09;&#xff0…

06-redis集群模式(中) 项目测试的云服务ip变内网等(解决大多数问题)

目录 0-0 前言 : 1. 搭建redis集群成功后 项目测试 ip变成内网 2. 设置 redis.conf的配置 3. 这时候如果运行后面操作, 会出以下问题 问题一: 不开放节点端口号 ​编辑问题二: 不开放通讯端口号 4. 最最核心的正确操作: 5. 删除全部容器 删除全部目录挂载 6. 重新运…

SSM(Vue3+ElementPlus+Axios+SSM前后端分离)-架子搭建

目录 SSM(Vue3ElementPlusAxiosSSM前后端分离)--架子搭建 技术栈 项目搭建 配置pom.xml 项目全局配置web.xml SpringMVC 配置 创建springDispatcherServlet-servlet.xml 创建项目相关的包 完成测试TestController.java 整合hi.html 启动Tomcat , 浏览器输入http://local…

mybatis是如何集成到spring的

前言 集成前的使用方式 mybatis单独使用时&#xff0c;一般的写法如下所示&#xff1a; // mybatis初始化 String resource "mybatis-config.xml"; InputStream inputStream Resources.getResourceAsStream(resource); // 读取配置文件&#xff0c;创建SqlS…

这五个问题一下就看出阿里通义千问和ChatGPT的差距了

前言 阿里通义千问申请过了&#xff0c;为了看看达到了什么水平&#xff0c;于是我问题了5个ChatGPT回答过的问题1&#xff0c;这五个问题网上都是没有的&#xff0c;是我自己想出来的。 问题一:小明说今天他吃了一只公鸡蛋&#xff0c;请问小明诚实吗&#xff1f; ChatGPT 这…

黑马Redis笔记高级篇 | 多级缓存

黑马Redis笔记高级篇 | 多级缓存&#xff08;黑马教程云服务器踩坑记录&#xff09; 1、JVM进程缓存&#xff08;tomcat服务内部&#xff09;1.1 导入商品案例1.2 初识Caffeine1.3 实现进程缓存 2、Lua语法入门2.1 初识Lua2.2 变量和循环2.3 条件控制、函数 3、多级缓存3.1 安装…

快速了解LVQ神经网络是什么

本站原创文章&#xff0c;转载请说明来自《老饼讲解-BP神经网络》bp.bbbdata.com 目录 一. 快速了解LVQ神经网络 1.1 LVQ神经网络是什么 1.2 LVQ神经网络的表示 二. 关于LVQ神经网络的判别计算过程 2.1 LVQ神经网络模型与它的判别方法 2.2 LVQ模型的…

【论文阅读】MINOTAUR: Multi-task Video Grounding From Multimodal Queries

背景动机 细粒度的视频理解已经成为增强现实(AR)和机器人应用开发的关键能力。为了达到这种级别的视频理解&#xff0c;智能体(例如虚拟助手)必须具备识别和推理视频中捕获的事件和对象的能力&#xff0c;处理一系列视觉任务&#xff0c;如活动检测、对象检索和(空间)时间基础…

教你设置dsn,brd文件关联到cadence

用过cadence的人应该都知道&#xff0c;很多人存在dsn,brd文件无法关联到cadence&#xff0c;从而导致无法直接双击对应的文件打开软件编辑&#xff0c;不得不先打开软件&#xff0c;再通过文件夹浏览来打开对应的文件&#xff0c;这其实是浪费了一些时间的。 下面通过简单的介…

Linux应用开发:socket

目录 1、TCP 1.1 TCP建立连接的流程图 1.2 TCP函数 1.2.1 socket 1.2.2 bind 1.2.3 listen 1.2.4 accept 1.2.5 recv 1.2.6 send 1.2.7 connnect 1.2.8 setsockopt、getsockopt 1.3 应用程序&#xff1a;服务器 1.4 应用程序&#xff1a;客户端 2、UDP 2.1 UDP建…

Github上传大于25M文件最简单方法!!!

Github上传大于25M文件最简单方法 方法&#xff1a;使用 GitHub 桌面应用程序1.下载 [Github](https://desktop.github.com/)应用程序到您的 Windows 或 Mac PC 上。2.单击“从互联网克隆存储库...”选项。3. 使用您的 Git 帐户登录。4. GitHub 应用程序将提示您使用电脑浏览器…

Docker安装Kong konga

一、安装Kong 1. 创建一个docker网络 docker network create kong-net2.拉取镜像 docker pull postgres:9.6 docker pull kong:2.6.03. 搭建pgsql数据库环境 docker run -d --name kong-database \--networkkong-net \-p 5432:5432 \-e "POSTGRES_USERkong" \-e …

Cisco Nexus 9000v Switch, NX-OS Release 10.3(3)F - 虚拟化的数据中心交换机

Cisco Nexus 9000v Switch, NX-OS Release 10.3(3)F - 虚拟化的数据中心交换机 请访问原文链接&#xff1a;https://sysin.org/blog/cisco-nexus-9000v/&#xff0c;查看最新版。原创作品&#xff0c;转载请保留出处。 作者主页&#xff1a;sysin.org NX-OS System SoftwareR…