优化青海湖至景点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这是不可能的任务。
测试样例
样例1:
输入:
distance = 500, n = 4, gas_stations = [[100, 1], [200, 30], [400, 40], [300, 20]]输出:4300
样例2:
输入:
distance = 1000, n = 3, gas_stations = [[300, 25], [600, 35], [900, 5]]输出:-1
样例3:
输入:
distance = 200, n = 2, gas_stations = [[100, 50], [150, 45]]输出:9000
样例4:
输入:
distance = 700, n = 5, gas_stations = [[100, 10], [200, 20], [300, 30], [400, 40], [600, 15]]输出:9500
样例5:
输入:
distance = 50, n = 1, gas_stations = [[25, 100]]输出:5000
代码解答
def solution(distance, n, gas_stations):
gas_stations = [[0, 0]] + gas_stations + [[distance, 0]]
n += 2
gas_stations.sort(key=lambda x: x[0])
dp = [[float('inf')] * 401 for _ in range(n)]
dp[0][200] = 0
for i in range(1, n):
dist = gas_stations[i][0] - gas_stations[i-1][0]
price = gas_stations[i][1]
stop = True
if i == n-1:
if 200 + dist <= 400:
return dp[i-1][200+dist]
else:
return -1
for j in range(401):
if dp[i-1][j] != float('inf') and j >= dist:
dp[i][j - dist] = min(dp[i][j - dist], dp[i-1][j])
for k in range(401 - (j - dist)):
dp[i][j - dist + k] = min(dp[i][j - dist + k], dp[i][j - dist] + k * price)
stop = False
if stop:
return -1
return -1
if __name__ == "__main__":
# 测试样例
gas_stations1 = [(100, 1), (200, 30), (400, 40), (300, 20)]
gas_stations2 = [(300, 25), (600, 35), (900, 5)]
gas_stations3 = [(100, 50), (150, 45)]
gas_stations4 = [(100, 10), (200, 20), (300, 30), (400, 40), (600, 15)]
gas_stations5 = [(25, 100)]
print(solution(500, 4, gas_stations1) == 4300)
print(solution(1000, 3, gas_stations2) == -1)
print(solution(200, 2, gas_stations3) == 9000)
print(solution(700, 5, gas_stations4) == 9500)
print(solution(50, 1, gas_stations5) == 5000)
代码思路
-
初始化加油站列表:
- 在
gas_stations列表的开头和结尾分别添加一个虚拟加油站,距离为0和目标距离,油价为0。这样做的目的是为了简化边界条件的处理。 - 将加油站列表按照距离进行排序。
- 在
-
动态规划数组初始化:
- 创建一个二维数组
dp,其中dp[i][j]表示到达第i个加油站时,油箱剩余j升油的最小成本。 - 初始化
dp[0][200]为0,表示在起始点油箱剩余200升油的成本为0。
- 创建一个二维数组
-
动态规划状态转移:
- 遍历每个加油站
i,计算从上一个加油站到当前加油站的距离dist和当前加油站的油价price。 - 对于每个可能的油量
j,如果可以从上一个加油站到达当前加油站(即j >= dist),则更新dp[i][j - dist]为dp[i-1][j]。 - 进一步,对于每个可能的加油量
k,更新dp[i][j - dist + k]为dp[i][j - dist] + k * price,表示在当前加油站加k升油的成本。
- 遍历每个加油站
-
边界条件处理:
- 如果到达最后一个加油站时,油量不足以到达目标地点(即
200 + dist > 400),则返回-1。 - 如果无法从上一个加油站到达当前加油站,则返回
-1。
- 如果到达最后一个加油站时,油量不足以到达目标地点(即
-
返回结果:
- 如果能够到达目标地点,返回
dp[n-1][200 + dist],即到达目标地点且油量剩余200升的最小成本。
- 如果能够到达目标地点,返回
注意
- 该算法的时间复杂度为
O(n * 400^2),其中n是加油站的数量。 - 空间复杂度为
O(n * 400),用于存储动态规划数组。