解题思路
我们可以使用动态规划(Dynamic Programming, DP)来解决这个问题。动态规划非常适合解决这类“在给定约束下最大化/最小化某个值”的问题。
算法步骤
-
定义状态:
- 使用一个数组
dp,其中dp[j]表示在预算为j时能租用的货船的最大总载货量。
- 使用一个数组
-
状态转移:
- 对于每种货船
(m, v, w),我们需要考虑在预算j内租用该货船的情况。 - 由于每种货船有数量限制
m,我们需要遍历每种货船的所有可用数量。 - 对于每个预算
j,我们需要更新dp[j],考虑是否租用当前货船。
- 对于每种货船
-
遍历顺序:
- 由于我们需要避免重复使用同一艘货船进行多次计算,内层循环应该从大到小遍历预算
j。
- 由于我们需要避免重复使用同一艘货船进行多次计算,内层循环应该从大到小遍历预算
代码
def solution(Q, V, ships):
# 初始化 dp 数组,长度为 V+1,所有元素初始化为 0
# dp[j] 表示在预算为 j 时能租用的货船的最大总载货量
dp = [0] * (V + 1)
# 遍历每种货船的信息 (m, v, w)
for m, v, w in ships:
# 对于当前货船,遍历其所有可用的数量 m
for _ in range(m):
# 从预算的最大值 V 开始,向前遍历到该货船的租赁成本 v(包含 v)
# 注意要逆序遍历,以避免重复使用同一艘货船进行多次计算
for j in range(V, v - 1, -1):
# 更新 dp[j],表示在预算为 j 时能得到的最大载货量
# 要么保持原来的值 dp[j],要么选择租用当前货船并加上剩余预算下的最大载货量 dp[j - v] + w
dp[j] = max(dp[j], dp[j - v] + w)
# 返回在预算 V 下的最大载货量
return dp[V]
if __name__ == "__main__":
# You can add more test cases here
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)
优化思路
-
二进制优化:
- 通过判断
k & (k - 1) == 0来确定k是否为2的幂次方。如果是,则count为k;否则,count为1。 - 这样可以减少内层循环的次数,因为每次只处理2的幂次方的数量。
- 通过判断
-
减少内层循环的次数:
- 内层循环从
V开始,向前遍历到v * count - 1,这样可以避免不必要的计算。
- 内层循环从