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

72 阅读3分钟

一、题目解析

这道题目来自豆包MarsCode AI 刷题平台,属于经典的多重背包问题,考察我们如何在预算限制下选择物品以实现收益最大化。题目背景是一个货船租赁问题:

  • 有 Q 种货船,每种货船的数量、租赁价格和最大载货量都已知;
  • 给定总预算 V,需要选择租赁哪些货船,以使总载货量最大。

从题目可以看出,这是一个组合优化问题,需要考虑预算、货船数量和收益之间的平衡。不同于普通的01背包问题,这里每种货船的数量有限,因此需要动态规划来处理这种约束条件。

二、思路分析

  1. 背包问题本质: 这道题可以抽象成一个背包问题,其中:

    • 背包容量:可用预算 V;
    • 物品重量:货船的租赁价格;
    • 物品价值:货船的最大载货量;
    • 每种货船的数量:物品数量的约束。

    本题属于多重背包问题,即每种物品(货船)的数量有限,需要在这个限制下选择最优组合。

  2. 动态规划思想: 我们使用动态规划来解决问题,定义 dp[j] 为在预算不超过 j 时,货船最大载货量的状态。主要步骤如下:

    • 初始化:将 dp 数组初始化为全零,因为预算为零时,最大载货量显然为 0。
    • 状态转移:对于每种货船,根据其数量,逐步更新当前预算下的最优解。
  3. 优化策略

    • 展开多重背包:对于每种货船,枚举可以选择的数量 k,将多重背包转化为多个01背包问题。
    • 从后往前遍历:为了防止状态重复计算,需要对 dp 数组进行从后向前的更新。

三、举例分析

假设我们有以下示例:

  • 输入:

    • Q = 2, V = 10
    • ships = [[2, 3, 2], [3, 2, 10]]

货船信息解释:

  • 第一种货船:最多租 2 艘,每艘价格 3,载货量 2;
  • 第二种货船:最多租 3 艘,每艘价格 2,载货量 10。

步骤

  1. 初始化
    dp = [0] * (V + 1),表示在预算从 0 到 10 的每个状态下,最大载货量为 0。

  2. 处理第一种货船
    选择 k = 1, 2 艘货船,分别更新 dp 数组。

    • 租 1 艘:预算 3 时,载货量增加到 2。
    • 租 2 艘:预算 6 时,载货量增加到 4。

    此时的 dp 数组为:

    dp = [0, 0, 0, 2, 0, 0, 4, 0, 0, 0, 0]

  3. 处理第二种货船
    选择 k = 1, 2, 3 艘货船,分别更新 dp 数组。

    • 租 1 艘:预算 2 时,载货量增加到 10。
    • 租 2 艘:预算 4 时,载货量增加到 20。
    • 租 3 艘:预算 6 时,载货量增加到 30。

    最终 dp 数组更新为:

    dp = [0, 0, 10, 20, 20, 30, 32, 30, 40, 40, 50]

最后,我们可以看到在预算 10 时,最大载货量为 32

四、代码实现

def solution(Q, V, ships):
    # Please write your code here
    dp = [0] * (V + 1)

    for m, v, w in ships:
        for j in range(V, v - 1, -1):  
            for k in range(1, m + 1):  
                if j >= k * v:  
                    dp[j] = max(dp[j], dp[j - k * v] + k * w)

    return dp[V]

五、总结

动态规划的本质是用状态转移方程描述问题,通过不断更新已知的最优解,最终找到全局最优解。这道题通过动态规划解决多重背包问题,考察了算法设计能力。关键在于灵活处理背包约束条件并构建合理的状态转移方程。