当前位置: 首页 > article >正文

动态规划(7):背包问题

引言

背包问题是动态规划中最经典、最重要的问题类型之一,它不仅在算法竞赛中频繁出现,也在实际应用中有着广泛的用途。从资源分配到投资组合优化,从生产计划到网络路由,背包问题的思想几乎无处不在。正因如此,背包问题被誉为动态规划的"必修课",掌握背包问题的解法对于理解和应用动态规划至关重要。

01背包问题详解

问题描述

01背包是最基础的背包问题,其描述如下:

有N件物品和一个容量为V的背包。第i件物品的重量是w[i],价值是v[i]。求解将哪些物品装入背包,可使这些物品的总重量不超过背包容量,且总价值最大。

名称"01"的由来是指对每件物品只有两种选择:要么选(用1表示),要么不选(用0表示)。

问题分析

01背包问题是一个典型的动态规划问题,我们可以通过以下步骤来解决:

  1. 状态定义:设dp[i][j]表示考虑前i件物品,背包容量为j时能获得的最大价值。

  2. 状态转移方程:对于第i件物品,有两种选择:

    • 不选择第i件物品:dp[i][j] = dp[i-1][j]
    • 选择第i件物品(前提是背包容量足够):dp[i][j] = dp[i-1][j-w[i]] + v[i]

    综合这两种情况,状态转移方程为:

    dp[i][j] = max(dp[i-1][j], dp[i-1][j-w[i]] + v[i])  (j >= w[i])
    dp[i][j] = dp[i-1][j]  (j < w[i])
    
  3. 初始状态:dp[0][j] = 0,表示没有物品可选时,无论背包容量多大,价值都为0。

  4. 最终结果:dp[N][V],表示考虑所有N件物品,背包容量为V时能获得的最大价值。

空间优化

上述解法的空间复杂度是O(N*V),但我们可以通过滚动数组的技巧将空间复杂度优化到O(V)。

观察状态转移方程可以发现,计算dp[i][j]时只需要用到dp[i-1][j]和dp[i-1][j-w[i]],也就是说,当前状态只与上一行的状态有关。因此,我们可以使用一维数组dp[j]来代替二维数组,其中dp[j]表示背包容量为j时能获得的最大价值。

但是,这里有一个关键点:为了避免在一次迭代中重复使用更新后的状态,我们需要从大到小遍历背包容量j。这样可以确保在计算dp[j]时,dp[j-w[i]]保存的仍然是上一轮的状态。

优化后的状态转移方程:

dp[j] = max(dp[j], dp[j-w[i]] + v[i])  (j >= w[i])

代码实现

// 01背包问题的一维动态规划解法
int knapsack01(int N, int V, vector<int>& w, vector<int>& v) {vector<int> dp(V + 1, 0);for (int i = 0; i < N; i++) {for (int j = V; j >= w[i]; j--) {dp[j] = max(dp[j], dp[j - w[i]] + v[i]);}}return dp[V];
}

实际应用

01背包问题在实际中有许多应用场景,例如:

  1. 资源分配:在有限资源下,如何选择项目以最大化收益。
  2. 投资决策:在有限资金下,如何选择投资组合以最大化回报。
  3. 货物装载:在有限空间内,如何选择货物以最大化价值。
  4. 任务调度:在有限时间内,如何选择任务以最大化完成的任务价值。

完全背包问题

问题描述

完全背包问题是01背包问题的一个变种。区别在于:01背包中每种物品只有一件,而完全背包中每种物品有无限件可用。

具体描述:有N种物品和一个容量为V的背包。第i种物品的重量是w[i],价值是v[i],每种物品有无限件可用。求解将哪些物品装入背包,可使这些物品的总重量不超过背包容量,且总价值最大。

问题分析

完全背包问题的分析思路与01背包类似,但状态转移方程有所不同:

  1. 状态定义:设dp[i][j]表示考虑前i种物品,背包容量为j时能获得的最大价值。

  2. 状态转移方程:对于第i种物品,可以选择0件、1件、2件…直到背包容量不足。但这样枚举会导致时间复杂度过高。我们可以通过优化状态转移方程来避免这种枚举:

    dp[i][j] = max(dp[i-1][j], dp[i][j-w[i]] + v[i])  (j >= w[i])
    

    注意这里与01背包的区别:在选择第i种物品时,我们使用的是dp[i][j-w[i]]而不是dp[i-1][j-w[i]],因为我们可以重复选择同一种物品。

  3. 初始状态:dp[0][j] = 0。

  4. 最终结果:dp[N][V]。

空间优化

与01背包类似,完全背包也可以使用一维数组进行空间优化。但是,由于状态转移方程的不同,完全背包在遍历背包容量时需要从小到大遍历,而不是从大到小。

优化后的状态转移方程:

dp[j] = max(dp[j], dp[j-w[i]] + v[i])  (j >= w[i])

代码实现

http://www.lryc.cn/news/2392004.html

相关文章:

  • 谷歌浏览器Google Chrome v137.0.7151.41 中文版本版+插件 v1.11.1
  • 《深入解析UART协议及其硬件实现》-- 第三篇:UART ASIC实现优化与低功耗设计
  • Hadoop常用端口号和配置文件
  • Apache Paimon:存储结构、写入及其源码分析
  • 19、Python字符串高阶实战:转义字符深度解析、高效拼接与输入处理技巧
  • 国芯思辰| 同步降压转换器CN2020应用于智能电视,替换LMR33620
  • 6个月Python学习计划 Day 8 - Python 函数基础
  • DeepSeek 提示词大全
  • 俄罗斯无人机自主任务规划!UAV-CodeAgents:基于多智能体ReAct和视觉语言推理的可扩展无人机任务规划
  • 结构性设计模式之Bridge(桥接)
  • CSS篇-1
  • Android 16系统源码_无障碍辅助(一)认识无障碍服务
  • 分布式数据库备份实践
  • 如何发布npm包?
  • 鸿蒙---使用真机模拟器的时候,图片不加载问题
  • 实验设计与分析(第6版,Montgomery)第5章析因设计引导5.7节思考题5.6 R语言解题
  • .NET 8使用AOT发布ASP.NET Core应用
  • OpenCV计算机视觉实战(8)——图像滤波详解
  • Docker 前端镜像容器部署指南
  • OpenAI大模型不听人类指令事件的技术分析与安全影响
  • 图神经网络实战——图的可视化
  • 自动化安全脚本学习
  • github公开项目爬取
  • 用豆包写单元测试
  • 传输层协议TCP(上)
  • Windows下安装并使用kubectl查看K8S日志
  • Hive 分区详解:从基础概念到实战应用
  • Android studio进阶开发(六)--如何用真机通过okhttp连接服务器
  • 如何解决网站服务器的异常问题?
  • WeakAuras Lua Script [ICC BOSS 11 - Sindragosa]