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

88 阅读3分钟

83 小S的货船租赁冒险

问题描述

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

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

测试样例

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

使用10号船和 31号船共花费9元能够载32单位的货,是10元以内能做到的最大载货量。

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

使用50号船共花费50元,能够载100个单位的货,是50元以内能做到的最大载货量。

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

由于只有一种情况,最多只能用100号船花费50元,从而达到500的载货量。即使没有花费到100元的上限。但总船数只有10所有只能载500的货。

解题思路

如果要暴力算出所有组合的情况显然数量级上并不合理,同时根据题意来看根据货币数量求最大载货量,很容易想到这是一个01背包问题。因此可以直接定义一个长度为V + 1的数组,dp[i]代表当预算为i时所能购买到的最大的载货量。 可以把元组[m[j], v[j], w[j]]当成m[j]艘不同的货船,只是刚好v[j]和w[j]是一样的。然后遍历所有的货船来更新dp数组。只不过需要注意的是不同的货船并非无限租赁的,有其固定的租赁数目上限。因此更新dp的时候需要倒序从V更新到最小值,从而避免重复利用当前循环更新的载货量。

def solution(Q, V, ships):
    dp = [-1] * (V + 1)
    dp[0] = 0
    for ship in ships:
        for i in range(ship[0]):
            # 倒序更新从V到ship[1]
            for j in range(V,  ship[1] - 1, -1):
                dp[j] = max(dp[j], dp[j - ship[1]] + ship[2])
    return max(dp)

复杂度分析

时间复杂度: 三层嵌套循环遍历,因此时间复杂度为O(Q * M * V)

空间复杂度: 额外开了长度为V + 1dp数组,因此空间复杂度为O(V)