动态规划~01背包问题

01背包问题
经典的0 - 1背包问题的解决方案。


二维数组的版本

代码功能概述

0 - 1背包问题指的是有 n 个物品和一个容量为 m 的背包,每个物品有对应的体积 v[i] 和价值 w[i],需要从这些物品里挑选若干个放入背包,让背包内物品的总价值达到最大。每个物品仅能选择放入或者不放入背包(即0 - 1选择)。

代码详细解释

#include<bits/stdc++.h>
using namespace std;// 定义长整型别名
typedef long long LL;
// 定义数组的最大长度
const int N=1100;// f[i][j] 表示前 i 个物品,背包容量为 j 时的最大价值
int f[N][N];
// v[i] 表示第 i 个物品的体积,w[i] 表示第 i 个物品的价值
int v[N],w[N];int main(){// n 表示物品的数量,m 表示背包的容量int n,m;// 从标准输入读取物品数量和背包容量cin>>n>>m;// 循环读取每个物品的体积和价值for(int i = 1;i<=n;i++){cin>>v[i]>>w[i];}// 动态规划求解过程for(int i = 1;i <= n;i++){for(int j = 1;j <= m;j++){// 如果当前背包容量 j 小于第 i 个物品的体积 v[i],则不能放入第 i 个物品if(j < v[i])// 最大价值等于前 i - 1 个物品在容量 j 下的最大价值f[i][j] = f[i-1][j];else// 可以选择放入或不放入第 i 个物品,取两者中的最大值f[i][j] = max(f[i-1][j],f[i-1][j-v[i]]+w[i]);}}// 输出前 n 个物品,背包容量为 m 时的最大价值cout<<f[n][m];return 0;
}

代码核心逻辑

  • 状态定义f[i][j] 代表前 i 个物品,背包容量为 j 时所能获得的最大价值。
  • 状态转移
    • j < v[i],也就是当前背包容量不足以放入第 i 个物品,那么 f[i][j] = f[i - 1][j]
    • j >= v[i],则可以选择放入或者不放入第 i 个物品:
      • 不放入:f[i][j] = f[i - 1][j]
      • 放入:f[i][j] = f[i - 1][j - v[i]] + w[i]
    • 取这两种情况的最大值作为 f[i][j] 的值。
  • 最终结果f[n][m] 即为前 n 个物品,背包容量为 m 时的最大价值。

复杂度分析

  • 时间复杂度 O ( n m ) O(nm) O(nm),这里的 n 是物品的数量,m 是背包的容量。
  • 空间复杂度 O ( n m ) O(nm) O(nm),主要是用于存储状态数组 f

要将你的二维动态规划代码优化为一维数组,可以利用动态规划的状态转移只依赖于上一行的状态这一特性。通过从右到左更新一维数组,可以避免覆盖还未使用的状态,从而实现空间优化。


一维数组的版本

优化后的代码

#include <bits/stdc++.h>
using namespace std;const int N = 1100;int f[N]; // 一维动态规划数组,f[j] 表示凑出金额 j 所需的最大价值
int v[N], w[N]; // v[i] 表示第 i 个物品的体积,w[i] 表示第 i 个物品的价值int main() {int n, m;cin >> n >> m; // 输入物品数量 n 和背包容量 mfor (int i = 1; i <= n; i++) {cin >> v[i] >> w[i]; // 输入每个物品的体积和价值}// 初始化动态规划数组memset(f, 0, sizeof(f)); // 初始时,所有金额的最大价值为 0// 动态规划求解for (int i = 1; i <= n; i++) { // 遍历每个物品for (int j = m; j >= v[i]; j--) { // 从大到小遍历背包容量f[j] = max(f[j], f[j - v[i]] + w[i]); // 更新状态}}// 输出结果cout << f[m] << endl; // 输出凑出金额 m 的最大价值return 0;
}

代码解释

1. 一维数组的定义
  • 原代码使用二维数组 f[i][j] 表示前 i 个物品在背包容量为 j 时的最大价值。
  • 优化后,使用一维数组 f[j] 表示背包容量为 j 时的最大价值。
  • 因为状态转移只依赖于上一行的状态,所以可以用一维数组代替二维数组。
2. 从右到左更新
  • 在更新 f[j] 时,f[j - v[i]] 表示未选择当前物品时的状态。
  • 如果从左到右更新(如 for (int j = v[i]; j <= m; j++)),会导致 f[j - v[i]] 被当前物品更新过,从而出现重复选择当前物品的情况。
  • 因此,必须从右到左更新(如 for (int j = m; j >= v[i]; j--)),确保每个物品只被选择一次。
3. 状态转移方程
  • 状态转移方程保持不变:
    f [ j ] = max ⁡ ( f [ j ] , f [ j − v [ i ] ] + w [ i ] ) f[j] = \max(f[j], f[j - v[i]] + w[i]) f[j]=max(f[j],f[jv[i]]+w[i])
    • f[j] 表示不选择当前物品时的最大价值。
    • f[j - v[i]] + w[i] 表示选择当前物品时的最大价值。
4. 初始化
  • 初始化 f 数组为 0,表示在没有物品时,所有背包容量的最大价值都为 0。
5. 输出结果
  • 最终结果存储在 f[m] 中,表示背包容量为 m 时的最大价值。

复杂度分析

时间复杂度
  • 外层循环遍历物品数量 n n n,内层循环遍历背包容量 m m m
  • 时间复杂度为 O ( n × m ) O(n \times m) O(n×m)
空间复杂度
  • 使用了一维数组 f,空间复杂度为 O ( m ) O(m) O(m)

注意事项

  1. 从右到左更新的重要性

    • 如果改为从左到右更新(如 for (int j = v[i]; j <= m; j++)),会导致每个物品被多次选择,变成 完全背包问题 的解法。
    • 因此,在 0-1 背包问题 中,必须从右到左更新。
  2. 适用场景

    • 这段代码适用于 0-1 背包问题,即每个物品只能选择一次。
    • 如果是 完全背包问题(每个物品可以无限次选择),需要将状态转移方程改为 f[j] = max(f[j], f[j - v[i]] + w[i]),并且内层循环改为从左到右更新。

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

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

相关文章

深入理解Java享元模式及其线程安全实践

引言 在软件系统中&#xff0c;当需要处理海量细粒度对象时&#xff0c;直接创建大量实例可能会导致内存消耗激增和性能下降。享元模式&#xff08;Flyweight Pattern&#xff09;通过共享对象内部状态&#xff0c;成为解决这类问题的经典方案。然而在多线程环境下&#xff0c…

1、mysql基础篇--概述

关系型数据库&#xff08;RDBMS&#xff09; 概念特点&#xff1a;数据模型&#xff1a; 概念 建立在关系模型基础上&#xff0c;有多张表相互连接的二维表组成的数据库 特点&#xff1a; 1、使用表存储&#xff0c;格式统一&#xff0c;便于维护 2、使用sql语言操作&#…

如何提升库存系统的高并发和稳定性:算法与设计模式

库存系统是企业运营的核心模块&#xff0c;尤其是在电商、零售和供应链管理中&#xff0c;系统的高并发和稳定性直接影响订单处理的准确性和效率。面对海量订单、复杂的库存管理需求&#xff0c;如何在高并发环境下确保库存数据的准确性和系统的稳定性&#xff1f;本文将从架构…

【多线程】synchronized底层实现的方式

前言 在java 开发中对于锁的应用非常的常见&#xff0c;如果对于什么时候该用什么锁&#xff0c;以及锁实现的原理有所不知道的&#xff0c;或者面试过程中面试官问你不知道怎么回答的&#xff0c;欢迎来看下面的文章 1、synchronized和ReentrantLock的区别 2、synchronized的…

Pytorch中Tensorboard的学习

1、Tensorboard介绍 TensorBoard 是 TensorFlow 开发的一个可视化工具&#xff0c;用于帮助用户理解和调试机器学习模型的训练过程。尽管它最初是为 TensorFlow 设计的&#xff0c;但通过 PyTorch 的 torch.utils.tensorboard 模块&#xff0c;PyTorch 用户也可以方便地使用 Te…

ETL 自动化:提升数据处理效率与准确性的核心驱动力

在数字化转型的浪潮中&#xff0c;数据已成为企业战略资产&#xff0c;高效处理数据的能力直接关系到企业的竞争力。ETL&#xff08;Extract, Transform, Load&#xff09;自动化作为数据处理领域的关键技术&#xff0c;正逐渐成为企业在数据时代脱颖而出、实现高效运营与精准决…

std::endl为什么C++ 智能提示是函数?

在使用vscode 的C智能提示后&#xff0c;输入endl 后&#xff0c;提示的却是std::endl(basic_ostream<CharT, Traits> &os), 感觉比较奇怪&#xff0c;各种代码里都是直接用的std::endl 啊&#xff0c; 这里怎么变成函数了呢&#xff1f; 在 C 中&#xff0c;std::en…

简洁、实用、无插件和更安全为特点的WordPress主题

简站WordPress主题是一款以简洁、实用、无插件和更安全为特点的WordPress主题&#xff0c;自2013年创立以来&#xff0c;凭借其设计理念和功能优势&#xff0c;深受用户喜爱。以下是对简站WordPress主题的详细介绍&#xff1a; 1. 设计理念 简站WordPress主题的核心理念是“崇…

数据结构篇:空间复杂度和时间复杂度

目录 1.前言&#xff1a; 1.1 学习感悟 1.2 数据结构的学习之路(初阶) 2.什么是数据结构和算法 2.1 数据结构和算法的关系 2.2 算法的重要性 2.3 如何衡量算法的好坏 3.时间复杂度 3.1 时间复杂度的概念 3.2 大O的渐进表示法 O() 4.空间复杂度 5. 常见的时间复杂度和…

node-ddk,electron,截屏封装(js-web-screen-shot)

node-ddk 截屏封装(js-web-screen-shot) https://blog.csdn.net/eli960/article/details/146207062 也可以下载demo直接演示 http://linuxmail.cn/go#node-ddk 感谢/第三方 本截屏工具, 使用的是: js-web-screen-shot https://www.npmjs.com/package/vue-web-screen-shot…

泰坦军团携手顺网旗下电竞连锁品牌树呆熊 共创电竞新纪元

在电竞行业的浪潮中&#xff0c;品牌之间的战略合作愈发成为推动市场前行的重要动力。最近&#xff0c;电竞显示器领域领军品牌泰坦军团高层领导出席顺网旗下电竞连锁品牌树呆熊十周年盛典。会议现场&#xff0c;双方高层领导宣布泰坦军团与树呆熊正式达成战略合作伙伴关系。 在…

HandyJSON原理

HandyJSON 的优势 JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式, 应用广泛. 在 App 的使用过程中, 服务端给移动端发送的大部分都是 JSON 数据, 移动端需要解析数据才能做进一步的处理. 在解析JSON数据这一块, 目前 Swift 中流行的框架基本上是 SwiftyJSON, …

信号的产生和保存

信号的产生 信号就是操作系统对用户操作做出的反应&#xff0c;但它的本质就是往操作系统写入信号&#xff0c;这是由操作系统的结构决定的。通过修改比特位来告诉操作系统接收信号和传了几号信号。 也正是因为我们身为用户无法亲自修改内核数据&#xff0c;所以我们需要通过操…

在C++ Qt中集成Halcon窗口并实现跨平台兼容和大图加载

目录 1. Halcon窗口嵌入Qt Widget 2. 处理大图加载 3. 多线程优化显示 4. 跨平台兼容性 1. Halcon窗口嵌入Qt Widget 将Halcon的HWindow控件嵌入到Qt的QWidget容器中,利用系统原生句柄实现跨平台。 #include <HalconCpp.h> #include <QWidget>class HalconWi…

深度学习技术与应用的未来展望:从基础理论到实际实现

深度学习作为人工智能领域的核心技术之一&#xff0c;近年来引起了极大的关注。它不仅在学术界带来了革命性的进展&#xff0c;也在工业界展现出了广泛的应用前景。从图像识别到自然语言处理&#xff0c;再到强化学习和生成对抗网络&#xff08;GAN&#xff09;&#xff0c;深度…

蓝光三维扫描技术:汽车零部件检测的精准高效之选

——汽车方向盘配件、保险杠塑料件、钣金件检测项目 汽车制造工业的蓬勃发展&#xff0c;离不开强大的零部件制造体系作支撑。汽车零部件作为汽车工业的基础&#xff0c;其设计水平、制造工艺、质量控制手段逐渐与国际标准接轨&#xff0c;对于零部件面差、孔位、圆角、特征线…

数据库联表Sql语句建一个新表(MySQL,Postgresql,SQL server)

数据库联表Sql语句建一个新表(MySQL,Postgresql,SQL server) 如果你想基于 SELECT USERS.ID,USERS.NAME,USERS.EMAIL,USERS.ID_CARD,USERS.V_CARD,USERS.ADDRESS,v_card.type,v_card.amount FROM USERS JOIN v_card on USERS.V_CARDv_card.v_card 这个查询结果创建一个新表&am…

六十天前端强化训练之第三十天之深入解析Vue3电商项目:TechStore全栈实践(文结尾附有源代码)

欢迎来到编程星辰海的博客讲解 看完可以给一个免费的三连吗&#xff0c;谢谢大佬&#xff01; 目录 深入解析Vue3电商项目&#xff1a;TechStore全栈实践 一、项目架构设计 二、核心功能实现 三、组合式API深度实践 四、性能优化实践 五、项目扩展方向 六、开发经验总结…

【人工智能】机器学习中的评价指标

机器学习中的评价指标 在机器学习中&#xff0c;评估指标&#xff08;Evaluation Metrics&#xff09;是衡量模型性能的工具。选择合适的评估指标能够帮助我们更好地理解模型的效果以及它在实际应用中的表现。 一般来说&#xff0c;评估指标主要分为三大类&#xff1a;分类、…

不同机床对螺杆支撑座的要求有哪些不同?

螺杆支撑座是机械设备中重要的支撑部件&#xff0c;其选择直接影响到设备的稳定性和使用寿命&#xff0c;尤其是在机床中&#xff0c;不同的机床对螺杆支撑座的要求也是不同的。 1、精度&#xff1a;精密测量用的基准平面和精密机床机械的检验测量设备&#xff0c;需要使用高精…