优化青海湖至景点X的租车路线成本
问题描述
小F计划从青海湖出发,前往一个遥远的景点X进行旅游。景点X可能是“敦煌”或“月牙泉”,线路的路径是唯一的。由于油价的不断上涨,小F希望尽量减少行程中的燃油成本。车辆的油箱容量为400L,在起始点租车时,车内剩余油量为 200L。每行驶 1km 消耗 1L 油。沿途设有多个加油站,小F可以在这些加油站补充燃油;此外,到达目标景点X还车的时候,需要保证车内剩余的油至少有 200L。
小F需要你帮助他计算,如果合理规划加油站的加油顺序和数量,最小化从青海湖到景点X的旅行成本(元)。
输入:
- distance:从青海湖到景点X的总距离(km),距离最远不超过 10000 km。
- n:沿途加油站的数量 (1 <= n <= 100)
- gas_stations:每个加油站的信息,包含两个非负整数(加油站距离起始点的距离(km), 该加油站的油价(元/L))
输出:
- 最小化从青海湖到景点X的旅行成本(元)。如果无法到达景点X,或者到达景点X还车时油料剩余不足 200L,则需要返回
-1告诉小F这是不可能的任务。
思路
- 每个加油站有不同的油价,我们需要选择性地加油以最小化费用。
- 从起点出发到达终点,油量必须在每个阶段都充足。每次加油要考虑油量是否足够到达下一个加油站或目标。
- 油量和加油站的选择之间存在相互依赖关系,需要在加油时合理选择,避免过多浪费和不必要的开销。
- 最小化总油费,且终点到达时油量不能低于200L。
为了实现最小化油费的目标,需要明确几个重要的限制条件:
1.从起点出发时,车辆油箱的初始油量为200L。
2.每行驶1km消耗1L油。
3.油箱的最大容量是400L,在到达终点时油箱剩余的油量必须至少为200L。
由于油费和油量之间有直接的联系,且每个加油站的油价不固定,因此需要通过动态规划来求解每一段行程的最小花费。
代码如下
def solution(distance, n, gas_stations):
# 添加终点加油站,距离目标点X的油价设为0
gas_stations.append((distance, 0))
gas_stations.sort(key=lambda x: x[0]) # 按加油站的距离进行排序
# 计算每两个相邻加油站之间的距离
dis = [0] * (n + 1)
dis[0] = gas_stations[0][0] # 从起点到第一个加油站的距离
for i in range(1, n + 1):
dis[i] = gas_stations[i][0] - gas_stations[i - 1][0] # 相邻加油站间的距离
# 初始化动态规划数组,dp[i][j]表示到第i个加油站,油量为j的情况下的最小油费
dp = [[float('inf')] * 401 for _ in range(n + 1)]
dp[0][200] = 0 # 起点油量为200L,花费为0
# 动态规划转移
for i in range(1, n + 1):
for j in range(401): # 当前油量
for k in range(401): # 上一个加油站的油量
if j + dis[i - 1] - k >= 0: # 确保油量足够到达下一个加油站
cost = (j + dis[i - 1] - k) * gas_stations[i - 1][1] # 计算加油费用
dp[i][j] = min(dp[i][j], dp[i - 1][k] + cost) # 更新最小油费
# 目标:到达终点并确保油量不低于200L
if dp[n][200] == float('inf'):
return -1
return dp[n][200] # 返回最小油费
代码解析
- 加油站排序:首先将所有加油站按距离从起点的顺序排序,确保每次计算时能够按照顺序遍历加油站。
- 计算距离:然后,计算相邻加油站之间的距离,便于后续计算油量消耗。
- 动态规划表初始化:创建一个动态规划表
dp,其中dp[i][j]表示在第i个加油站时油量为j时的最小花费。初始状态为dp[0][200] = 0,表示从起点出发,油量为200L时花费为0。 - 状态转移:遍历所有加油站,并根据油量的变化更新动态规划表。在每次转移时,计算到达某个加油站的油量,并更新最小花费。
- 最终判断:如果无法到达终点,返回-1;否则,返回最小油费。
时间复杂度
动态规划的时间复杂度为O(n * 401 * 401),其中n为加油站的数量。由于每个加油站需要遍历所有可能的油量状态(最大为400L),并且每个状态的转移需要遍历前一个加油站的所有可能油量。