第五讲 二维费用的背包问题

【题目来源】AcWing 8. 二维费用的背包问题

【题意分析】
本题在前面背包问题的基础上,增加了一个维度——质量,背包拥有了容积、承重两个限制,物品也有了体积、质量两种属性。
【参考资料】第一讲 0/1背包问题
与0/1背包类似,加入一层循环限制重量即可:

#include<iostream>
using namespace std;
const int N1 = 1050;
const int N2 = 110;
struct node{
   
   
  int v, m, w;
} q[N1];
int n, V, M;
int dp[N1][N2][N2];
//1000 * 100 * 100 = 107,1000ms能过

### 二维费用背包问题动态规划算法实现 #### 基本概念 二维费用背包问题是传统背包问题的一个扩展版本,在该问题中,每件物品不仅有一个价值,还有两个不同的成本(例如重量和体积)。目标是在不超过两种资源限制的情况下最大化总价值。这种问题通常可以通过动态规划来解决。 #### 状态定义与转移方程 设 `dp[i][j]` 表示在第一种资源剩余容量为 `i`,第二种资源剩余容量为 `j` 的情况下能够获得的最大价值。对于第 `k` 个物品,其对应的两种成本分别为 `cost1[k]` 和 `cost2[k]`,对应的价值为 `value[k]`。状态转移方程可以表示为: ```plaintext dp[i][j] = max(dp[i][j], dp[i - cost1[k]][j - cost2[k]] + value[k]) ``` 其中,只有当 `i >= cost1[k]` 且 `j >= cost2[k]` 时才能进行更新[^1]。 #### 初始条件 初始状态下,所有的 `dp[i][j]` 都设置为 0,即没有任何物品被放入背包时,最大价值为 0。 #### 实现代码 以下是基于 C++二维费用背包问题动态规划实现代码: ```cpp #include <iostream> #include <vector> #include <algorithm> using namespace std; // 定义二维费用背包问题的函数 int twoDimensionalKnapsack(int n, int capacity1, int capacity2, vector<int>& cost1, vector<int>& cost2, vector<int>& value) { // 创建并初始化 DP 数组 vector<vector<int>> dp(capacity1 + 1, vector<int>(capacity2 + 1, 0)); // 动态规划填表过程 for (int k = 0; k < n; ++k) { for (int i = capacity1; i >= cost1[k]; --i) { for (int j = capacity2; j >= cost2[k]; --j) { dp[i][j] = max(dp[i][j], dp[i - cost1[k]][j - cost2[k]] + value[k]); } } } return dp[capacity1][capacity2]; } int main() { // 示例数据 int n = 3; int capacity1 = 5, capacity2 = 6; vector<int> cost1 = {2, 3, 4}; vector<int> cost2 = {1, 2, 3}; vector<int> value = {5, 7, 9}; // 调用二维费用背包函数,并输出结果 int result = twoDimensionalKnapsack(n, capacity1, capacity2, cost1, cost2, value); cout << "The maximum value is: " << result << endl; return 0; } ``` 这段代码展示了如何通过嵌套循环遍历所有可能的状态组合,并依据状态转移方程计算最终的结果[^2]。 #### 时间复杂度分析 假设共有 `n` 个物品,第一种资源的容量上限为 `m`,第二种资源的容量上限为 `v`,则时间复杂度为 O(n*m*v),因为我们需要对每一个物品以及每一种可能的资源组合都执行一次比较操作。 #### 空间优化 如果只需要得到最后的答案而不需要记录具体的选择方案,则可以进一步减少空间占用量至一维数组形式。不过需要注意的是,此时内部两层循环的方向必须调整为从高向低迭代以防止重复使用同一个物品多次的情况发生[^5]。 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值