问题描述
小U计划进行一场从地点A到地点B的徒步旅行,旅行总共需要 M 天。为了在旅途中确保安全,小U每天都需要消耗一份食物。在路程中,小U会经过一些补给站,这些补给站分布在不同的天数上,且每个补给站的食物价格各不相同。 小U需要在这些补给站中购买食物,以确保每天都有足够的食物。现在她想知道,如何规划在不同补给站的购买策略,以使她能够花费最少的钱顺利完成这次旅行。
- M:总路程所需的天数。
- N:路上补给站的数量。
- p:每个补给站的描述,包含两个数字 A 和 B,表示第 A 天有一个补给站,并且该站每份食物的价格为 B 元。
保证第0天一定有一个补给站,并且补给站是按顺序出现的。
思路解析
这道问题是一个动态规划问题,目标是找到最低的成本来完成一场徒步旅行,确保每天都有足够的食物。问题的关键点在于:
- 补给站的使用:选择哪些补给站、何时购买食物以保证最低花费。
- 动态规划的状态设计:记录到每一天所需的最小花费。
分解步骤
-
状态定义: 使用
dp[day]表示到达第day天时所需的最小花费。 -
状态转移: 对于每一个补给站
(supply_day, price),如果在supply_day购买食物,可以满足未来day的需求(day - supply_day天的食物需求)。更新公式为:
dp[day]=min(dp[day],dp[supply_day]+(day−supply_day)×price)
- 初始条件:
dp[0] = 0表示第 0 天无需花费任何成本。- 其余天数初始设为无穷大
float('inf'),表示还未计算到达该天的最小花费。
-
目标: 最终结果是
dp[m],即到达第m天的最小花费。 -
边界条件:
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. 主函数
-
保留本身提供的测试用例,验证函数的正确性。