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

动态规划(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])

代码实现

相关文章:

  • 如何查看 GitLab 内置的 PostgreSQL 版本?
  • 华为OD机试真题——单词接龙(首字母接龙)(2025A卷:100分)Java/python/JavaScript/C/C++/GO最佳实现
  • HTTP与HTTPS网络原理(7000+字详解)
  • 小土堆pytorch--损失函数与反向传播
  • python神经网络学习小结2
  • 从OTA双雄「共舞」,透视旅游持续繁荣背后的结构性跃迁
  • 【Fifty Project - D31】
  • BERT分类器和朴素贝叶斯分类器比较
  • 鸿蒙OSUniApp 开发实时天气查询应用 —— 鸿蒙生态下的跨端实践#三方框架 #Uniapp
  • 鸿蒙OSUniApp 制作自定义的下拉刷新控件#三方框架 #Uniapp
  • leetcode:2235. 两整数相加(python3解法,数学相关算法题)
  • 开源软件协议大白话分类指南
  • Java中的设计模式:单例模式的深入探讨
  • 11 接口自动化-框架封装之统一请求封装和接口关联封装
  • leetcode98.验证二叉搜索树:递归法中序遍历的递增性验证之道
  • 君正Ingenic webRTC P2P库libyangpeerconnection7编程指南
  • leetcode:2160. 拆分数位后四位数字的最小和(python3解法,数学相关算法题)
  • C++之STL入门
  • 探索LobeChat:开源、可定制的下一代AI对话客户端
  • Spring + MyBatis/MyBatis-Plus 分页方案(limit分页和游标分页)详解
  • 镇江网站建设远航网络/广州网页搜索排名提升
  • 网站制作价格表模板/外链大全
  • 三丰云怎么做网站/广州新一期lpr
  • 优质的网站建设推广/百度推广优化公司
  • 专门做服装批发的网站吗/百度最新版app下载安装
  • 网站论坛建设方案/苏州网络推广seo服务