38.补给站最优花费问题 思路与代码分析| 豆包MarsCode AI刷题

89 阅读3分钟

问题描述

小U计划进行一场从地点A到地点B的徒步旅行,旅行总共需要 M 天。为了在旅途中确保安全,小U每天都需要消耗一份食物。在路程中,小U会经过一些补给站,这些补给站分布在不同的天数上,且每个补给站的食物价格各不相同。 小U需要在这些补给站中购买食物,以确保每天都有足够的食物。现在她想知道,如何规划在不同补给站的购买策略,以使她能够花费最少的钱顺利完成这次旅行。

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

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

思路解析

这道问题是一个动态规划问题,目标是找到最低的成本来完成一场徒步旅行,确保每天都有足够的食物。问题的关键点在于:

  1. 补给站的使用:选择哪些补给站、何时购买食物以保证最低花费。
  2. 动态规划的状态设计:记录到每一天所需的最小花费。

分解步骤

  1. 状态定义: 使用 dp[day] 表示到达第 day 天时所需的最小花费。

  2. 状态转移: 对于每一个补给站 (supply_day, price),如果在 supply_day 购买食物,可以满足未来 day 的需求(day - supply_day 天的食物需求)。更新公式为:

dp[day]=min⁡(dp[day],dp[supply_day]+(day−supply_day)×price)
  1. 初始条件
  • dp[0] = 0 表示第 0 天无需花费任何成本。
  • 其余天数初始设为无穷大 float('inf'),表示还未计算到达该天的最小花费。
  1. 目标: 最终结果是 dp[m],即到达第 m 天的最小花费。

  2. 边界条件

  • supply_day <= day,确保补给站在到达 day 之前可用。

代码解析

以下是代码分步解析:

1. 初始化 dp:

dp = [float('inf')] * (m + 1)
dp[0] = 0
  • 设定初始条件,第 0 天的花费为 0,其余设为无穷大。

2. 遍历所有天数:

for day in range(m + 1):
  • 从第 0 天到第 m 天,逐天计算最低花费。

3. 遍历补给站:

for supply in p:
    supply_day, price = supply
    if supply_day <= day:
  • 对于每一个补给站,如果它的天数在当前天数之前,计算从该补给站购买食物的可能性。

4. 更新 dp:

dp[day] = min(dp[day], dp[supply_day] + food_needed * price)
  • 将从补给站购买食物的花费加入动态规划数组,更新最低花费。

5. 返回结果:

return dp[m]
  • 最终输出到达第 m 天的最小花费。

6. 主函数

  • 保留本身提供的测试用例,验证函数的正确性。