问题描述
小S在码头租用货船,面临一个优化问题:在有限的预算内,如何选择不同类型货船的组合以最大化总载货量。这个问题是一个典型的动态规划问题,可以通过构建一个二维数组来解决。
问题分析
首先,我们需要理解题目中的几个关键参数:
Q:货船的种类数量。V:小S可用的总预算。ships:一个列表,包含每种货船的数量m[i]、租赁价格v[i]和每艘货船的最大载货量w[i]。
我们的目标是在不超过预算V的前提下,计算出能够租用的货船的最大总载货量。
思路解析
解决这个问题的关键在于使用动态规划(DP)的思想。我们可以定义一个二维数组dp,其中dp[i][j]表示在前i种货船中,预算为j时的最大载货量。通过遍历每一种货船和每一种预算,我们可以逐步构建这个数组。
算法详解与代码实现
-
初始化DP数组: 创建一个
Q+1行V+1列的二维数组dp,所有元素初始化为0。dp[0][j]表示没有货船时,预算为j的最大载货量,显然为0。def solution(Q, V, ships): 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): dp[i][j] = dp[i - 1][j] # 不选择第 i 种货船 -
选择当前货船的不同数量: 我们需要计算在当前预算下,选择不同数量的当前货船能够得到的最大载货量。
for k in range(1, min(m, j // v) + 1): if j >= k * v: dp[i][j] = max(dp[i][j], dp[i - 1][j - k * v] + k * w) -
返回结果: 最终,
dp[Q][V]将包含在所有货船和预算V下的最大载货量。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)
个人思考
在解决这个问题时,我意识到动态规划是一种强大的工具,它允许我们在复杂问题中寻找最优解。通过将问题分解为更小的子问题,并存储这些子问题的解,我们可以避免重复计算,从而提高算法的效率。此外,我也认识到在实际应用中,问题的具体细节(如货船的数量限制)对算法的设计和实现有着重要影响。在编写代码时,我特别注意了如何清晰地表达算法的逻辑,以及如何通过测试样例来验证算法的正确性。通过这个过程,我加深了对动态规划和算法调试的理解。