DP:背包问题----0/1背包问题

文章目录

  • 💗背包问题
    • 💛背包问题的变体
    • 🧡0/1 背包问题的数学定义
    • 💚解决背包问题的方法
    • 💙例子
  • 💗解决背包问题的一般步骤?
  • 💗例题
  • 💗总结

在这里插入图片描述

❤️❤️❤️❤️❤️博客主页:lyyyyrics❤️❤️❤️❤️❤️
在这里插入图片描述

💗背包问题

背包问题(Knapsack Problem)是一类经典的组合优化问题,在计算机科学和数学中有广泛应用。其基本问题是:

  • 输入:给定一个容量为 W W W 的背包和 n n n 个物品,每个物品 i i i 有一个重量 w i w_i wi 和一个价值 v i v_i vi
  • 目标:选择若干个物品放入背包,使得总重量不超过背包的容量 W W W,并且总价值最大化。

💛背包问题的变体

  1. 0/1 背包问题:每个物品只能选择一次,即要么选中(1)要么不选(0)。
  2. 分数背包问题:每个物品可以分割,即可以选择物品的一部分。
  3. 多重背包问题:每个物品有多个副本,可以选择多个相同的物品。
  4. 多维背包问题:背包有多个限制条件,例如容量和体积等。

🧡0/1 背包问题的数学定义

目标函数:
maximize ∑ i = 1 n c i ⋅ x i \text{maximize} \sum_{i=1}^{n} c_i \cdot x_i maximizei=1ncixi
其中, n n n 表示物品的数量, c i c_i ci 表示物品 i i i 的价值。

约束条件:
∑ i = 1 n w i ⋅ x i ≤ C \sum_{i=1}^{n} w_i \cdot x_i \leq C i=1nwixiC
其中, w i w_i wi 表示物品 i i i 的重量, C C C 表示背包的容量。

其它约束条件:
x i ∈ { 0 , 1 } x_i \in \{0,1\} xi{0,1}
i = 1 , 2 , 3 , … , n i = 1,2,3,\ldots,n i=1,2,3,,n
其中, x i x_i xi 表示物品 i i i 是否被选中。

💚解决背包问题的方法

解决背包问题的方法有很多,包括动态规划、分支定界法、贪心算法(适用于分数背包问题)以及各种近似算法和启发式算法等。

💙例子

假设有一个背包容量为 50 的背包,有以下物品:

物品重量价值
11060
220100
330120

目标是选择物品使得总重量不超过 50 且总价值最大化。在这个例子中,最佳选择是选取物品 2 和物品 3,总重量为 50,总价值为 220。

💗解决背包问题的一般步骤?

背包问题是一个经典的优化问题,可以通过动态规划算法来解决。下面是解决背包问题的一般步骤:

  1. 确定问题的约束条件:背包的容量限制和物品的重量和价值。

  2. 定义状态:将问题拆解为多个子问题,定义状态为背包的容量和可选择的物品。

  3. 定义状态转移方程:根据子问题的定义,确定状态之间的关系。例如,对于背包问题,可以定义状态转移方程为f(i,j),表示在前i个物品中选择,背包容量为j时,可以获得的最大价值。则可以得到状态转移方程:f(i,j) = max(f(i-1,j), f(i-1,j-w[i])+v[i]),其中w[i]和v[i]分别表示第i个物品的重量和价值。

  4. 确定初始条件:确定边界条件,即背包容量为0时,价值为0。

  5. 通过动态规划算法计算最优解:根据状态转移方程和初始条件,利用循环或递归的方式计算最优解。

  6. 回溯最优解:根据计算得到的最优解,可以通过回溯的方式确定选择了哪些物品放入背包中,从而得到最终的解。

需要注意的是,背包问题的解决方法还包括贪心算法、分支界限算法等。具体选择哪种方法取决于问题的约束条件和需要优化的目标。

💗例题

题目链接
题目:

在这里插入图片描述

样例输出和输入:

在这里插入图片描述

这道题并不是leetcode的那种接口的模式,而是ACM模式,我们需要进行完整的输入和输出,我们先分析第一个样例:

0123
容量241
价值1054

第一个问题是给定一个背包容量,求出当背包的容量不用装满时的最大价值,意思就是我们选出的物品的总的容量可以小于背包的容量,也可以等于背包的容量,这时,我们可以第一个物品和三个物品的价值是最大的。
总价值为14,
第二个问题是我们必须将 背包容量给塞满,求塞满的状态的物品的最大价值,这种情况下有可能是没有结果的,因为无法选出能将背包塞满的组合 ,所以这时候就输出零。但是这个例子是可以输出结果的,塞满的情况应该是第二个物品和第三个物品,总价值是9,所以最后输出14和9。

算法原理:
状态表示:dp[i][j]-----表示选到第i个位置时的所有选法中的不超过总容积j的最大价值。
状态转移方程:在这里插入图片描述
这是不把背包填满的情况下的状态转移方程,还有一个问题就是需要将背包填满。
在这里插入图片描述
所以这里如果要用到前一个状态的话,应该判断一下前一个状态是否是-1,如果前一个状态是-1的话,就表示这种情况根本不存在 ,所以不能选择这种状态在这里插入图片描述

初始化:第一个问题的初始化只需要将dp表初始化为0,第二个问题的初始化上面已经讨论过了。
填表顺序:也是按照从左上角到右下角,依次填表。
返回值:返回dp[n][V]
代码展示:

#include <cstring>
#include <iostream>
#include<string>
using namespace std;//数据范围
const int N = 1010;
//n个数据,V为背包的总容量,v表示单个物品的所占容积,w表示单个物品所含的价值
int n, V, v[N], w[N];
//i表示第i个位置,j表示总的容积
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++){//j表示容量for (int j = 1;j <= V;j++){//不选的情况dp[i][j] = dp[i - 1][j];//如果能选,则和之前不选的情况求一个maxif (j >= v[i])dp[i][j] = max(dp[i][j], dp[i - 1][j - v[i]] + w[i]);}}//输出最后一个dp状态cout << dp[n][V] << endl;//重置dp表,将表中数据重置为0memset(dp, 0, sizeof dp);//单独初始化第一排的后面的位置,因为如果没有任何物品根本不可能有价值,所以初始化为-1for (int i = 1;i <= V;i++){//初始化不存在dp的位置dp[0][i] = -1;}for (int i = 1;i <= n;i++){//j表示容量for (int j = 1;j <= V;j++){//可以不选dp[i][j] = dp[i - 1][j];//如果要选择当前位置的话需要考虑前一个状态是否是-1,选不到的情况 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]);}}//如果不存在选满的情况,直接返回0,否则返回dp[n][V]位置的值cout << (dp[n][V] == -1 ? 0 : dp[n][V]) << endl;return 0;
}

代码优化:
可以利用滚动数组进行优化:

#include <cstring>
#include <iostream>
#include<string>
using namespace std;//数据范围
const int N = 1010;
//n个数据,V为背包的总容量,v表示单个物品的所占容积,w表示单个物品所含的价值
int n, V, v[N], w[N];
//i表示第i个位置,j表示总的容积
int dp[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++)//j表示容量for (int j = V;j >= v[i];j--)//修改遍历顺序//如果能选,则和之前不选的情况求一个maxdp[j] = max(dp[j], dp[j - v[i]] + w[i]);//输出最后一个dp状态cout << dp[V] << endl;//重置dp表,将表中数据重置为0memset(dp, 0, sizeof dp);//单独初始化第一排的后面的位置,因为如果没有任何物品根本不可能有价值,所以初始化为-1for (int i = 1;i <= V;i++)//初始化不存在dp的位置dp[i] = -1;for (int i = 1;i <= n;i++)//j表示容量for (int j = V;j >= v[i];j--)//修改遍历顺序//如果能选,则和之前不选的情况求一个maxif(dp[j-v[i]]!=-1)dp[j] = max(dp[j], dp[j - v[i]] + w[i]);//如果不存在选满的情况,直接返回0,否则返回dp[n][V]位置的值cout << (dp[V] == -1 ? 0 : dp[V]) << endl;return 0;
}

运行结果:
在这里插入图片描述

💗总结

通过对0/1背包问题的分析和动态规划解法的详细讲解,我们可以看到这种经典问题在算法设计中的重要性。0/1背包问题不仅是许多实际应用的基础,也是理解和掌握动态规划思想的一个重要实例。

在解决0/1背包问题时,关键在于构建状态转移方程并合理使用空间和时间资源。通过递归和迭代的方法,我们能更好地理解背包问题的解法,优化算法效率,并提升解决复杂问题的能力。

希望这篇博客能帮助你理解0/1背包问题的基本原理和解法,同时激发你对动态规划和算法设计的进一步兴趣和探索。未来的学习中,不妨尝试更多的变种背包问题和动态规划问题,以不断提升自己的算法技能和编程水平。

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

毕业季有感

本文介绍一些刚毕业、即将入职前的随想与心得。 毕业和上班无缝衔接。要离开北京了&#xff0c;来到天津。 我一向很喜欢探索新环境&#xff0c;每一次要到新的学校、新的城市、新的单位都会很激动&#xff1b;这一次也是一样&#xff0c;在一开始几乎只有对新环境的憧憬。但是…

rocketmq-console可视化界面功能说明

rocketmq-console可视化界面功能说明 登录界面OPS(运维)Dashboard(驾驶舱)Cluster(集群)Topic(主题)Consumer(消费者)Producer(生产者)Message(消息)MessageTrace(消息轨迹) rocketmq-console是rocketmq的一款可视化工具&#xff0c;提供了mq的使用详情等功能。 本章针对于rock…

【机器学习】机器学习重塑广告营销:精准触达,高效转化的未来之路

&#x1f4dd;个人主页&#x1f339;&#xff1a;Eternity._ &#x1f339;&#x1f339;期待您的关注 &#x1f339;&#x1f339; ❀目录 &#x1f4d2;1. 引言&#x1f4d9;2. 机器学习基础与广告营销的结合&#x1f9e9;机器学习在广告营销中的核心应用领域&#x1f339;用…

CSRF靶场通关合集

目录 前言 CSRF漏洞总结 1.PiKachu靶场 1.1CSRF(get) 1.2 CSRF(post)请求 1.3 CSRF Token 2.DVWA靶场 难度低 难度中 难度高 前言 最近系统的将从web渗透到内网渗透的知识点做一个回顾,同时结合一些实战的案例来演示,下面是对刚开始学习时对靶场的一个总结. CSRF漏洞…

LLM - 循环神经网络(RNN)

1. RNN的关键点&#xff1a;即在处理序列数据时会有顺序的记忆。比如&#xff0c;RNN在处理一个字符串时&#xff0c;在对字母表顺序有记忆的前提下&#xff0c;处理这个字符串会更容易。就像人一样&#xff0c;读取下面第一个字符串会更容易&#xff0c;因为人对字母出现的顺序…

LabVIEW汽车转向器测试系统

绍了一种基于LabVIEW的汽车转向器测试系统。该系统集成了数据采集、控制和分析功能&#xff0c;能够对转向器进行高效、准确的测试。通过LabVIEW平台&#xff0c;实现了对转向器性能参数的实时监测和分析&#xff0c;提升了测试效率和数据精度&#xff0c;为汽车转向器的研发和…

《Windows API 每日一练》8.4 edit控件

编辑类是最简单的预定义窗口类&#xff0c;而另一方面却又是最复杂的。当你用“edit”作为类名创建子窗口时&#xff0c;可以基于CreateWindow调用的x坐标、y坐标、宽度和高度参数定义一个矩形。这个矩形包含可编辑的文本。一旦子窗口控件获得输入焦点&#xff0c;你就可以输入…

(南京观海微电子)——MOS管原理及应用区别

MOS管&#xff1a; 全称为金属氧化物半导体场效应管&#xff08;Metal Oxide Semiconductor Field Effect Transistor&#xff09;&#xff0c;也被称为MOSFET&#xff08;Metal-Oxide-Semiconductor Field-Effect Transistor&#xff09;。它是一种半导体器件&#xff0c;常用…

【PB案例学习笔记】-27制作一个控制任务栏显示与隐藏的小程序

写在前面 这是PB案例学习笔记系列文章的第27篇&#xff0c;该系列文章适合具有一定PB基础的读者。 通过一个个由浅入深的编程实战案例学习&#xff0c;提高编程技巧&#xff0c;以保证小伙伴们能应付公司的各种开发需求。 文章中设计到的源码&#xff0c;小凡都上传到了gite…

240706_昇思学习打卡-Day18-基于MindSpore的GPT2文本摘要

240706_昇思学习打卡-Day18-基于MindSpore的GPT2文本摘要 今天做一个根据一段文章提取摘要的提取器&#xff0c;基于nlpcc2017摘要数据&#xff0c;内容为新闻正文及其摘要&#xff0c;就是训练集及标签。 首先我们来预装以下MindSpore环境 %%capture captured_output # 实验…

vb.netcad二开自学笔记2:认识vs编辑器

认识一下宇宙第一编辑器的界面图标含义还是很重要的&#xff0c;否则都不知道面对的是什么还怎么继续&#xff1f; 一、VS编辑器中常见的图标的含义 变量 长方体&#xff1a;变量 局部变量 两个矩形块&#xff1a;枚举 预定义的枚举 紫色立方体&#xff1a;方法 橙色树状结构…

数据结构——二叉树相关题目

1.寻找二叉树中数值为x的节点 //寻找二叉树中数值为x的节点 BTNode* TreeFind(BTNode* root, BTDataType x)//传过来二叉树的地址和根的地址&#xff0c;以及需要查找的数据 {if (root Null){return Null;}//首先需要先判断这个树是否为空&#xff0c;如果为空直接返回空if (…

筛选Github上的一些优质项目

每个项目旁都有标签说明其特点&#xff0c;如今日热捧、多模态、收入生成、机器人、大型语言模型等。 项目涵盖了不同的编程语言和领域&#xff0c;包括人工智能、语言模型、网页数据采集、聊天机器人、语音合成、AI 代理工具集、语音转录、大型语言模型、DevOps、本地文件共享…

《Programming from the Ground Up》阅读笔记:p19-p48

《Programming from the Ground Up》学习第2天&#xff0c;p19-p48总结&#xff0c;总计30页。 一、技术总结 1.object file p20, An object file is code that is in the machine’s language, but has not been completely put together。 之前在很多地方都看到object fi…

IDEA中使用Maven打包及碰到的问题

1. 项目打包 IDEA中&#xff0c;maven打包的方式有两种&#xff0c;分别是 install 和 package &#xff0c;他们的区别如下&#xff1a; install 方式 install 打包时做了两件事&#xff0c;① 将项目打包成 jar 或者 war&#xff0c;打包结果存放在项目的 target 目录下。…

C++_STL---list

list的相关介绍 list是可以在常数范围内在任意位置进行插入和删除的序列式容器&#xff0c;并且该容器可以前后双向迭代。 list的底层是带头双向循环链表结构&#xff0c;链表中每个元素存储在互不相关的独立节点中&#xff0c;在节点中通过指针指向其前一个元素和后一个元素。…

Google重大更新--解读Android Auto认证4.3

Google在今年五月更新了Android Auto 4.2.2版本&#xff0c;而在2024年7月他们推出了Android Auto 4.3版本&#xff0c;这是自2023年9月以来对Android Auto 4.2版本的一次重大更新。 为了确保合规性和顺利认证&#xff0c;OEM和Tire1必须确保PDK组件版本与正在认证的主机的Rece…

Docker学习笔记(二)镜像、容器、仓库相关命令操作

一、docker镜像操作 列出镜像列表 我们可以使用 docker images 来列出本地主机上的镜像。 各个选项说明: REPOSITORY&#xff1a;表示镜像的仓库源 TAG&#xff1a;镜像的标签 IMAGE ID&#xff1a;镜像ID CREATED&#xff1a;镜像创建时间 SIZE&#xff1a;镜像大小 查…

存储结构与管理磁盘

前言&#xff1a;本博客仅作记录学习使用&#xff0c;部分图片出自网络&#xff0c;如有侵犯您的权益&#xff0c;请联系删除 目录 一、一切从“/”开始 二、物理设备的命名规则 三、文件系统与数据资料 四、挂载硬件设备 五、添加硬盘设备 六、添加交换分区 七、磁盘容…

uniapp报错--app.json: 在项目根目录未找到 app.json

【问题】 刚创建好的uni-app项目&#xff0c;运行微信小程序控制台报错如下&#xff1a; 【解决方案】 1. 程序根目录打开project.config.json文件 2. 配置miniprogramRoot&#xff0c;指定小程序代码的根目录 我的小程序代码编译后的工程文件目录为&#xff1a;dist/dev/mp…