问题重述
小S需在预算V内租用Q种货船,每种货船有固定数量m、租赁成本v和载货量w,求能租用的最大总载货量。
思路分析
-
明确目标:
- 小S的目标是在给定的预算 V 内,租用货船以承载最大的总货物量。
-
定义状态:
- 使用动态规划(DP)来解决问题。定义一个数组
dp,其中dp[j]表示在预算为j时能租用的货船的最大总载货量。
- 使用动态规划(DP)来解决问题。定义一个数组
-
初始化状态:
- 初始化
dp数组,所有元素都设为 0。这表示在没有预算时,无法租用任何货船,因此载货量为 0。
- 初始化
-
状态转移:
- 遍历每种货船,对于每种货船,再遍历其所有可用的数量。
- 对于每种货船的每个实例,从预算的最大值 V 开始向前遍历到该货船的租赁成本 v[i](注意要包括 v[i],因此是
range(V, v[i] - 1, -1))。 - 在遍历过程中,更新
dp[j]的值。如果租用当前货船,则新的载货量为dp[j - v[i]] + w[i](即剩余预算下的最大载货量加上当前货船的载货量)。比较这个值与dp[j]的原值,取较大者作为新的dp[j]值。
-
结果输出:
- 遍历完成后,
dp[V]即为在预算 V 下能租用的货船的最大总载货量。
- 遍历完成后,
-
算法复杂度:
- 时间复杂度:O(Q * m[i] * V),其中 Q 是货船种类数量,m[i] 是第 i 种货船的数量,V 是总预算。因为对于每种货船的每个实例,都需要遍历从 V 到 v[i] 的所有预算值。
- 空间复杂度:O(V),因为需要使用一个大小为 V+1 的数组来存储动态规划的状态。
代码分析
1.- 函数 solution 接收三个参数:货船种类数量 Q(虽然未在函数内部直接使用,但可以作为输入验证的一部分)、总预算 V 和货船信息列表 ships。
- 初始化一个长度为
V+1的动态规划数组dp,用于存储不同预算下的最大载货量。 - 通过嵌套循环遍历每种货船及其数量,并逆序更新
dp数组,以确保在计算当前预算下的最大载货量时,已经考虑了所有可能的子问题解。 - 使用
max函数比较当前载货量与选择租用当前货船后的新载货量,以更新dp数组的值。 - 最终返回
dp[V],即在总预算V下能租用的货船的最大总载货量。
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]
2.- 主程序部分使用 if __name__ == "__main__": 来确保当脚本作为主程序运行时才执行以下代码。
- 定义了两个测试用例
ships和ships2,分别包含不同的货船信息。 - 对于每个测试用例,调用
solution函数并传入相应的参数(货船种类数量、总预算和货船信息列表),然后验证返回的结果是否与预期值相等。 - 使用
print函数输出结果验证的结果,以便于观察测试是否通过。
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]] # 第二个测试用例的货船信息
# 调用 solution 函数并验证结果
print(solution(2, 10, ships) == 32) # 验证第一个测试用例的结果
print(solution(23, 400, ships2) == 1740) # 验证第二个测试用例的结果
总结
上述代码使用动态规划解决货船租赁问题,计算在给定预算内能租用的货船的最大总载货量,并验证了两个测试用例。