AI 刷题 38.补给站最优花费问题 动态规划题解| 豆包MarsCode AI 刷题

168 阅读3分钟

38.补给站最优花费问题

问题描述

小U计划进行一场从地点A到地点B的徒步旅行,旅行总共需要 M 天。为了在旅途中确保安全,她每天都需要消耗一份食物。在这段路程中,小U会经过一些补给站,这些补给站分布在不同的天数上,并且每个补给站的食物价格各不相同。

小U需要在这些补给站中购买食物,以确保每天都有足够的食物。现在她想知道,如何规划在不同补给站的购买策略,以使她能够花费 最少的钱 顺利完成这次旅行。

  • M:总路程所需的天数。
  • N:路上补给站的数量。
  • p:每个补给站的描述,包含两个数字 A 和 B,表示第 A 天有一个补给站,并且该站每份食物的价格为 B 元。

保证第0天一定有一个补给站,并且补给站是按顺序出现的。

示例

输入:

  1. m = 5, n = 4, p = [[0, 2], [1, 3], [2, 1], [3, 2]]

    • 输出:7
  2. m = 6, n = 5, p = [[0, 1], [1, 5], [2, 2], [3, 4], [5, 1]]

    • 输出:6
  3. m = 4, n = 3, p = [[0, 3], [2, 2], [3, 1]]

    • 输出:9

解题思路

为了帮助小U以最低的花费完成旅程,我们可以利用动态规划的方法。以下是解题步骤:

  1. 动态规划表定义

    • 定义一个数组 dp[i],表示在第 i 天结束时的最小花费。
  2. 初始化

    • dp[0] = 0,因为在第0天不需要花费。
  3. 状态转移

    • 对于每一天,从 1M,遍历每个补给站,检查在当前天数之前的补给站,计算从该补给站到当前天的购买成本。
    • 更新 dp[i] 为当前计算出的最小花费。
  4. 结果输出

    • 返回 dp[m],即第 M 天的最小花费。

解题代码

def solution(m, n, p):
    # dp[i] 表示在第 i 天结束时的最小花费
    dp = [float('inf')] * (m + 1)
    
    # 初始化第0天的花费
    dp[0] = 0
    
    # 遍历每一天
    for i in range(1, m + 1):
        # 遍历每个补给站
        for j in range(n):
            if p[j][0] < i:
                # 计算从第 p[j][0] 天到第 i 天的成本
                cost = (i - p[j][0]) * p[j][1]
                dp[i] = min(dp[i], dp[p[j][0]] + cost)
    
    return dp[m]

# 测试样例
print(solution(5, 4, [[0, 2], [1, 3], [2, 1], [3, 2]]))  # 输出 7
print(solution(6, 5, [[0, 1], [1, 5], [2, 2], [3, 4], [5, 1]]))  # 输出 6
print(solution(4, 3, [[0, 3], [2, 2], [3, 1]]))  # 输出 9

解题思路详细解析

在上述代码中,我们使用了一个动态规划数组 dp 来存储每一天结束时的最低花费。我们先初始化第0天的花费为0,表示小U在出发之前并不需要花费。

通过双重循环,外层循环遍历每一天,内层循环遍历所有补给站。我们检查每个补给站是否在当前天之前,然后计算从该补给站到当前天的成本。如果这一成本加上到达补给站的最低花费小于当前记录的最小花费,我们就更新 dp[i]

最终,dp[m] 将包含小U完成旅行所需的最低花费。

复杂度分析

  • 时间复杂度:O(M * N),最坏情况下,我们需要遍历每一天并检查所有补给站,这可能会导致 M 天和 N 个补给站相乘的复杂度。
  • 空间复杂度:O(M),我们使用一个一维数组 dp 存储每一天的最小花费,所需额外的空间与天数成正比。