这个问题是典型的 0/1 背包问题 的变种,具体地说,它是一个 多重背包问题。我们有多个货船的种类,每种货船有一定的数量,可以选择多个同样的货船,目的是在预算限制内最大化载货量。
问题分析:
- 每个货船种类有
m[i]个,每艘的租赁价格为v[i],最大载货量为w[i]。 - 我们需要根据预算
V,选择合适的货船组合,使得总的载货量最大。
解题思路:
由于每种货船的数量 m[i] 是有限的,因此不能像 0/1 背包问题那样只选择或不选择,而是可以选择多个(但数量上限为 m[i])。这就引出了 多重背包问题。
对于每个货船种类,我们可以使用以下几种方法来处理:
- 暴力枚举法:可以考虑每个货船种类选择
0个到m[i]个货船(类似于把每个货船看作多个背包物品)。 - 优化处理:将每个货船种类的选择问题看作多个物品的选择问题,从而使用动态规划来解决。
动态规划解决方案:
我们使用一个一维 dp 数组,其中 dp[j] 表示在预算为 j 时,能够获得的最大载货量。
- 初始化时,
dp[0] = 0,表示没有花费时的最大载货量为 0,其他dp[j]初始化为 0。 - 对于每个货船种类,我们可以选择多个相同的货船,因此我们可以采用 多重背包 的转移方式。
对于每种货船,如果我们选择 k 艘货船(其中 k 的取值范围为 0 到 m[i]),我们可以更新 dp[j]。
实现步骤:
- 对每种货船类型,从预算
V到租赁价格v[i]逆序遍历(避免重复选择同一艘货船)。 - 对于每个选择的货船数量
k(从 1 到最多可选择的数量),更新dp[j]。
def solution(Q, V, ships):
# dp[j] 表示在预算为 j 时的最大载货量
dp = [0] * (V + 1)
# 遍历每种货船
for m, v, w in ships:
# 对于每种货船,使用多重背包的优化方法
# 逆序遍历,防止重复选择
for j in range(V, v - 1, -1):
# 对每个可能选择的货船数量(从1到m个)
for k in range(1, m + 1):
cost = v * k
if j >= cost:
dp[j] = max(dp[j], dp[j - cost] + w * k)
else:
break
return dp[V]
复杂度分析:
- 时间复杂度:对于每种货船,内部会遍历最多
V次,并且对每种货船最多会选择m[i]次。因此时间复杂度是O(Q * V * m),其中Q是货船的种类数,V是预算,m是每种货船的数量。 - 空间复杂度:空间复杂度为
O(V),因为我们只使用了一个大小为V + 1的dp数组。
输入:`Q = 2,V = 10,ships = [[2, 3, 2], [3, 2, 10]]`
输出:`32`
- 第一个货船类型(最多2艘,每艘价格3元,载货量2):最多可以选择2艘,总价格6元,载货量4。
- 第二个货船类型(最多3艘,每艘价格2元,载货量10):最多可以选择3艘,总价格6元,载货量30。
选择 2 艘第二类货船,总价格 6,载货量 30;再选择 1 艘第一类货船,总价格 3,载货量 2。总载货量是 32。