问题描述
小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
针对问题的思路:
-
理解问题:我们需要在给定的预算
V内,选择不同类型的货船,使得总载货量最大化。每种货船有数量限制、租赁成本和载货量。 -
数据结构选择:我们可以使用动态规划来解决这个问题。定义一个二维数组
dp,其中dp[i][j]表示在前i种货船中,使用不超过j元的预算所能获得的最大载货量。 -
状态转移方程:
- 对于每种货船
(m[i], v[i], w[i]),我们可以选择租用0到m[i]艘。 - 状态转移方程为:
dp[i][j] = max(dp[i-1][j], dp[i-1][j-k*v[i]] + k*w[i]),其中k是从0到m[i]的整数。
- 对于每种货船
-
初始化:
dp[0][j] = 0表示没有货船时,无论预算多少,载货量都是0。 -
最终结果:
dp[Q][V]即为所求的最大载货量。
算法步骤
- 初始化
dp数组:dp[i][j]表示在前i种货船中,使用不超过j元的预算所能获得的最大载货量。 - 遍历每一种货船:对于每一种货船,遍历所有可能的预算。
- 尝试租用不同数量的当前货船:对于每一种货船,尝试租用
0到m[i]艘,更新dp[i][j]。 - 返回最大载货量:
dp[Q][V]即为所求的最大载货量。
代码实现
# 初始化 dp 数组,dp[i][j] 表示在前 i 种货船中,使用不超过 j 元的预算所能获得的最大载货量
dp = [[0] * (V + 1) for _ in range(Q + 1)]
# 遍历每一种货船
for i in range(1, Q + 1):
m, v, w = ships[i - 1]
# 遍历预算
for j in range(V + 1):
# 尝试租用不同数量的当前货船
for k in range(min(m, j // v) + 1):
# 更新 dp[i][j]
dp[i][j] = max(dp[i][j], dp[i - 1][j - k * v] + k * w)
# 返回最大载货量
return dp[Q][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)