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
使用1艘0号船和 3艘1号船共花费9元能够载32单位的货,是10元以内能做到的最大载货量。
输入:
Q = 3,V = 50,ships = [[5, 10, 20], [2, 20, 30], [3, 15, 25]]
输出:100
使用5艘0号船共花费50元,能够载100个单位的货,是50元以内能做到的最大载货量。
输入:
Q = 1,V = 100,ships = [[10, 5, 50]]
输出:500
由于只有一种情况,最多只能用10艘0号船花费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 + 1的dp数组,因此空间复杂度为O(V)。