问题描述
一个旅行者外出旅行时需要将 n 件物品装入背包,背包的总容量为 m。每个物品都有一个重量和一个价值。你需要根据这些物品的重量和价值,决定如何选择物品放入背包,使得在不超过总容量的情况下,背包中物品的总价值最大。
给定两个整数数组 weights 和 values,其中 weights[i] 表示第 i 个物品的重量,values[i] 表示第 i 个物品的价值。你需要输出在满足背包总容量为 m 的情况下,背包中物品的最大总价值。
思路解析
这个问题是一个经典的0/1背包问题,我们通常使用动态规划来解决。以下是解题的思路:
目标: 在给定背包容量 m 下,选择的物品使得总重量不超过 m,同时我们需要让背包中的总价值最大。
特性:
- 每个物品要么选,要么不选。并不是每个物品都需要进行选择
- 动态规划的核心是 决策选择 和 状态转移。
动态规划的定义
假设 数组dp[j] 是表示在容量 j 下,可以获得的最大价值。因此,我们的最终目标是求 dp[m]。
状态转移方程
对于每个物品 i:
- 如果不选第 i个物品,价值为
dp[j](继承上一状态)。 - 如果选择第 i 个物品,价值为
dp[j - weights[i]] + values[i](减去重量,加上价值)。 状态转移的公式如下:
初始化
- 初始
dp[j]全部为 0,因为没有物品时,任何容量下价值都是 0。
优化方向
动态规划通常通过二维数组表示:dp[i][j] 表示前 i 个物品在容量 j 下的最大价值。
但可以优化为一维数组 dp[j],从后向前遍历容量 j,避免覆盖影响。
代码详解
- 初始化:
- 创建一维数组
dp,大小为 m+1,所有值初始化为 0。
- 创建一维数组
- 物品选择:
- 外层循环遍历物品,内层从容量 m 向 weights[i]倒序更新。
- 倒序更新避免覆盖之前未处理的数据。
- 更新规则:
- 每次取当前状态和加入当前物品后的状态的较大值。
复杂度分析
- 时间复杂度:
- 外层遍历物品 O(n),内层遍历容量 O(m),总复杂度为 O(n⋅m)。
- 空间复杂度:
- 使用一维数组 dp,复杂度为 O(m)。