刷题笔记-小S的货船租赁冒险 | 豆包MarsCode AI刷题

86 阅读4分钟

小S的货船租赁冒险

问题分析

这道题要求在给定的预算 V 元内,从 Q 种不同类型的货船中选择一些船只进行租赁,使得所租用的船只的总载货量最大。每种货船有一定的数量限制 m[i],租赁价格 v[i],以及每艘船的最大载货量 w[i]

核心问题:在有限的预算和每种货船数量限制下,如何选择租赁的船只组合,使得总载货量最大化。

抽象模型

该问题可以抽象为多重背包问题(Bounded Knapsack Problem)

  • 物品:每种货船视为一种物品,每个物品有数量限制。
  • 价值:每艘货船的载货量 w[i]
  • 成本:租赁每艘货船的价格 v[i]
  • 目标:在总成本不超过预算 V 的前提下,选择物品使得总价值(载货量)最大。

解题思路

1. 朴素多重背包

最直观的方法是使用多重背包的动态规划算法,时间复杂度为 O(Q×V×Mmax)O(Q \times V \times M_{\text{max}}),其中 MmaxM_{\text{max}} 是货船数量的最大值。但是由于每种货船的数量可能较大,直接套用多重背包的做法会导致时间复杂度过高,无法通过所有测试用例。

2. 二进制优化多重背包

为了解决上述问题,我们采用二进制优化的方法,将多重背包问题转化为多个0-1背包问题,从而降低时间复杂度。

二进制优化的原理

对于每种货船的数量 m[i],我们可以将其拆分成若干个物品,其数量为二进制形式。例如:

  • 如果 m[i] = 5,我们可以将其拆分为数量为 1, 2, 2 的三个物品(1+2+2=51 + 2 + 2 = 5)。
  • 这样,每个新的物品的数量都是1,我们可以将其视为0-1背包问题的物品。
具体步骤
  1. 拆分物品:对于每种货船,将其数量按照二进制拆分。例如,对于数量 m[i],拆分成若干个数量为 k 的物品,k 依次为 1,2,4,1, 2, 4, \dots,直到总和达到 m[i]

  2. 更新动态规划:使用0-1背包的动态规划方法,对于拆分后的每个物品,按照其成本和价值更新DP数组。

3. 动态规划实现

  • 状态定义:设定一维DP数组,dp[c]表示在总成本不超过 c 的情况下,可以获得的最大总载货量。

  • 状态转移:对于每个拆分后的物品(成本为 cost = v[i] * count,价值为 value = w[i] * count),对于所有的 cVcost,更新 dp[c] = max(dp[c], dp[c - cost] + value)

算法实现

def solution(Q, V, ships):
    dp = [0] * (V + 1)
    for m_i, v_i, w_i in ships:
        k = 1
        counts = []
        while m_i > 0:
            count = min(k, m_i)
            counts.append(count)
            m_i -= count
            k <<= 1  # k *= 2
        for count in counts:
            cost = v_i * count
            value = w_i * count
            for c in range(V, cost - 1, -1):
                if dp[c - cost] + value > dp[c]:
                    dp[c] = dp[c - cost] + value
    return dp[V]

算法分析

时间复杂度

  • 拆分物品:对于每种货船,最多需要拆分 log2m[i]\log_2 m[i] 次,总共最多需要处理 O(log2m[i])O(\sum \log_2 m[i]) 个物品。

  • 动态规划:对于每个物品,内层循环为从 Vcost,总的时间复杂度为 O(物品总数×V)O(\text{物品总数} \times V)

  • 总体时间复杂度O(N×V)O(N \times V),其中 N 为拆分后的物品总数,远小于原始的物品总数 Q \times M_{\text{max}}

空间复杂度

  • 使用了一维DP数组,空间复杂度为 O(V)O(V)

总结

通过将多重背包问题转换为0-1背包问题,我们有效地降低了时间复杂度,使得算法可以在合理的时间内处理较大的输入规模。这种二进制优化的方法是解决多重背包问题的经典技巧,值得在类似的问题中借鉴和应用。

拓展思考

  • 完全背包问题:如果每种货船的数量无限,可以使用完全背包的解法。

  • 优化空间:如果需要进一步优化空间,可以考虑滚动数组等技巧。

  • 应用场景:该问题的解法在资源分配、预算管理等实际问题中有广泛的应用价值。