AI 刷题 313.0、1背包问题 | 豆包MarsCode AI刷题

64 阅读4分钟

0、1背包问题

题目描述

一个旅行者外出旅行时需要将 nnn 件物品装入背包,背包的总容量为 mmm。每个物品都有一个重量和一个价值。你需要根据这些物品的重量和价值,决定如何选择物品放入背包,使得在不超过总容量的情况下,背包中物品的总价值最大。

给定两个整数数组 weightsvalues,其中 weights[i] 表示第 iii 个物品的重量,values[i] 表示第 iii 个物品的价值。你需要输出在满足背包总容量为 mmm 的情况下,背包中物品的最大总价值。

题目解析

这个问题是经典的“0/1背包问题”,它要求我们在一个固定容量的背包中选择物品,使得物品的总价值最大。这里的挑战在于如何在给定的容量和物品之间做出选择,以使背包中物品的总价值最大化。

我们可以采用动态规划(Dynamic Programming,DP)的方法来解决这个问题。动态规划方法可以通过状态转移方程在 O(n×m)O(n \times m)O(n×m) 的时间复杂度内解决问题,适用于背包容量较大时。

方法介绍
为了求解这个背包问题,我们可以使用一个二维数组 dp[i][j],其中 i 表示前 iii 个物品,j 表示背包的容量。dp[i][j] 的含义是:前 iii 个物品在容量为 jjj 的背包中能取得的最大价值。

状态转移方程

对于每个物品 iii 和背包容量 jjj,我们有两种选择:

  1. 不放入背包:此时,dp[i][j] = dp[i-1][j]
  2. 放入背包:此时,dp[i][j] = dp[i-1][j - weight[i]] + value[i],前提是 j≥weight[i]j \geq weight[i]j≥weight[i]。

最终,dp[n][m] 就是我们所需要的最大价值。

动态规划实现

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int knapsack(int m, const vector<int>& weights, const vector<int>& values) {
int n = weights.size();
vector<vector<int>> dp(n + 1, vector<int>(m + 1, 0));  // dp[i][j]表示前i个物品放入容量为j的背包的最大价值

// 动态规划求解
for (int i = 1; i <= n; ++i) {
    for (int j = 1; j <= m; ++j) {
        // 不放第i个物品
        dp[i][j] = dp[i - 1][j];
        // 放第i个物品
        if (j >= weights[i - 1]) {
            dp[i][j] = max(dp[i][j], dp[i - 1][j - weights[i - 1]] + values[i - 1]);
        }
    }
}

// dp[n][m]是我们想要的最大总价值
return dp[n][m];
}

 int main() {
vector<int> weights = {2, 3, 4, 5};  // 每个物品的重量
vector<int> values = {3, 4, 5, 6};   // 每个物品的价值
int m = 5;  // 背包容量

cout << "最大价值为: " << knapsack(m, weights, values) << endl;

return 0;
}

代码解析

输入:我们首先定义了物品的重量数组 weights 和价值数组 values,以及背包的总容量 m

DP数组:我们用二维数组 dp 来记录每一个状态的最大价值。dp[i][j] 表示使用前 iii 个物品,容量为 jjj 的背包所能获得的最大价值。

状态转移:对于每个物品 iii 和背包容量 jjj,我们有两种选择:

 不放该物品:`dp[i][j] = dp[i - 1][j]`。
 放该物品:如果背包容量 j≥weights[i−1]j \geq weights[i-1]j≥weights[i−1],那么 `dp[i][j] = max(dp[i][j], dp[i - 1][j - weights[i - 1]] + values[i - 1])`。

最终结果:dp[n][m] 表示前 nnn 个物品在容量为 mmm 的背包中可以获得的最大价值。

代码演示

假设我们有以下数据:

物品的重量:{2, 3, 4, 5} 物品的价值:{3, 4, 5, 6} 背包容量:5

输出

最大价值为: 7

这个结果表示,在容量为 5 的背包中,选择前两个物品(重量为 2 和 3,价值分别为 3 和 4),能够获得的最大总价值为 7。

时间复杂度分析

动态规划算法的时间复杂度为 O(n×m)O(n \times m)O(n×m),其中 nnn 是物品的数量,mmm 是背包的容量。这个时间复杂度对于大部分背包问题来说已经是相当高效的,尤其是在背包容量 mmm 较大时。

总结

这个问题是典型的“背包问题”,使用动态规划(DP)是解决这类问题的一种常见且高效的方法。通过定义状态转移方程,我们能够逐步计算出背包中物品的最大总价值。