青训营X豆包AI工具的使用 | 小S的货船租赁冒险 | 豆包MarsCode AI 刷题

113 阅读4分钟

问题描述

小S在码头租用货船,有 Q 种不同类型的货船可供选择。每种货船有固定的数量 m[i]、租赁成本 v[i] 和最大载货量 w[i]。小S希望在预算 V 元内,租用能够承载最大总货物的货船组合。每种货船的具体信息包括数量、租赁价格和载货量。小S需要你帮忙计算在给定预算下,她能租用的货船的最大总载货量是多少。

  • Q: 货船的种类数量。
  • V: 李华可用的总预算(单位:元)。
  • ships: 一个列表,其中每个元素是一个元组 [m[i], v[i], w[i]],分别表示第 i 种货船的数量、租赁价格和每艘货船的最大载货量。

测试样例

样例1:

输入:Q = 2,V = 10,ships = [[2, 3, 2], [3, 2, 10]]
输出:32

样例2:

输入:Q = 3,V = 50,ships = [[5, 10, 20], [2, 20, 30], [3, 15, 25]]
输出:100

样例3:

输入:Q = 1,V = 100,ships = [[10, 5, 50]]
输出:500

样例4:

输入:Q = 4,V = 100,ships = [[1, 100, 200], [2, 50, 100], [3, 33, 66], [4, 25, 50]]
输出:200

样例5:

输入:Q = 2,V = 300,ships = [[100, 1, 1], [50, 5, 10]]
输出:550

问题理解

你需要在给定的预算 V 元内,选择不同类型的货船,使得总载货量最大化。每种货船有数量限制、租赁成本和载货量。

数据结构选择

  • 动态规划 (DP):这是一个典型的背包问题变种,可以使用动态规划来解决。
  • DP数组dp[j] 表示在预算为 j 元时,能够租用的最大载货量。

算法步骤

  1. 初始化:创建一个长度为 V+1 的 DP 数组,初始值为 0。
  2. 遍历每种货船:对于每种货船,遍历其数量。
  3. 更新 DP 数组:从后往前更新 DP 数组,避免重复计算。对于每个预算 j,更新 dp[j] 为 max(dp[j], dp[j - v] + w),其中 v 是当前货船的租赁成本,w 是当前货船的载货量。
  4. 返回结果:最终 dp[V] 就是在预算 V 元下的最大载货量。

关键点

  • 从后往前更新:这样可以避免在同一轮中重复使用同一艘货船。
  • 数量限制:每种货船的数量限制需要在遍历时考虑。

原始的 01背包 01背包的状态转移方程为 f[i][j] = max(f[i - 1][j], f[i - 1][j - w[i]] + v[j])

i代表对i件物体做决策,有两种方式—放入背包和不放入背包。 j表示当前背包剩余的容量。

转移方程的解释: 创建一个状态矩阵f,横坐标 i 是物体编号,纵坐标 j 为背包容量。 首先将 f 第0行和第0列初始化为0 (代码里面将整个f初始化为0了,其实只初始化第0行和第0列就够了)。这个表示不放物体时最大价值为0 。(物体编号从1开始)

    # 初始化 dp 数组
    dp = [0] * (V + 1)
    
    # 遍历每种货船
    for m, v, w in ships:
        # 遍历每种货船的数量
        for _ in range(m):
            # 从后往前更新 dp 数组,避免重复计算
            for j in range(V, v - 1, -1):
                dp[j] = max(dp[j], dp[j - v] + w)
    
    # 返回在预算 V 下的最大载货量
    return dp[V]
 
if __name__ == "__main__":
    # 你可以添加更多测试用例
    ships = [[2, 3, 2], [3, 2, 10]]
    ships2 = [[30, 141, 47], [9, 258, 12], [81, 149, 13], [91, 236, 6], [27, 163, 74], [34, 13, 58], [61, 162, 1], [80, 238, 29], [36, 264, 28], [36, 250, 2], [70, 214, 31], [39, 116, 39], [83, 287, 4], [61, 269, 94], [23, 187, 46], [78, 33, 29], [46, 151, 2], [71, 249, 1], [67, 76, 85], [72, 239, 17], [61, 256, 49], [48, 216, 73], [39, 49, 74]]
    print(solution(2, 10, ships) == 32)
    print(solution(23, 400, ships2) == 1740)