问题描述
小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
问题理解
小F需要从青海湖出发,前往一个遥远的景点X,沿途有多个加油站。车辆的油箱容量为400L,初始油量为200L,每行驶1km消耗1L油。小F需要在加油站补充燃油,目标是尽量减少行程中的燃油成本。到达景点X时,车内剩余油量至少为200L。 例子和输入输出修改过,之前写的C++跑不了了,py试一下算了
数据结构选择
-
加油站信息:
- 使用一个列表
gasStations存储每个加油站的信息,每个元素是一个包含两个整数的元组(距离, 油价)。
- 使用一个列表
-
动态规划数组:
- 使用一个二维数组
dp,其中dp[i][j]表示到达第i个加油站时,油箱剩余油量为j时的最小花费。
- 使用一个二维数组
算法步骤
-
初始化:
- 将
gasStations按照距离升序排序。 - 初始化
dp数组,dp[0][200] = 0,表示在起点(青海湖)时,油箱剩余200L,花费为0。
- 将
-
动态规划计算:
- 对于每个加油站
i,计算从上一个加油站到当前加油站的距离distances[i-1]。 - 对于每个可能的油量
j,计算从上一个加油站到当前加油站的最小花费。 - 更新
dp[i][j],确保在当前加油站加油后,油量不超过400L,且花费最小。
- 对于每个加油站
-
判断是否可以到达终点:
- 计算到达终点时的剩余油量
remaining_fuel_at_destination。 - 如果剩余油量超过400L或小于0,返回
-1。
- 计算到达终点时的剩余油量
-
计算最小花费:
- 遍历
dp[n][i],找到到达终点时的最小花费。
- 遍历
-
时间复杂度:
- O(n * maxCapacity^2)
import sys
def solution(distance, n, gasStations):
maxCapacity = 400
inf = float('inf')
gasStations.sort(key=lambda x: x[0]) # 按照加油站位置升序排序
# 计算每个加油站之间的距离
distances = [gasStations[0][0]] # 从青海湖到第一个加油站的距离
for i in range(1, len(gasStations)):
distances.append(gasStations[i][0] - gasStations[i-1][0])
# 初始化 dp 数组
dp = [[inf] * (maxCapacity + 1) for _ in range(n + 2)]
dp[0][200] = 0 # 初始状态,容量为200,花费为0
# 动态规划计算最小花费
for i in range(1, n + 1):
for j in range(maxCapacity + 1):
for k in range(maxCapacity + 1):
if len(gasStations[i-1]) != 2:
raise ValueError(f"Invalid gas station data at index {i-1}: {gasStations[i-1]}")
if j + distances[i-1] - k >= 0 and k >= distances[i-1]:
dp[i][j] = min(dp[i][j], dp[i-1][k] + (j + distances[i-1] - k) * gasStations[i-1][1])
# 判断是否可以到达终点
remaining_fuel_at_destination = 200 + distance - gasStations[n-1][0]
if remaining_fuel_at_destination > maxCapacity or remaining_fuel_at_destination < 0:
return -1
# 最小花费
min_cost = inf
for i in range(remaining_fuel_at_destination , maxCapacity + 1):
min_cost = min(min_cost , dp[n][i])
if min_cost == inf:
return -1
return min_cost
def min(a, b):
return a if a < b else b
if __name__ == "__main__":
# You can add more test cases here
gas_stations1 = [(100, 1), (200, 30), (400, 40), (300, 20)]
gas_stations2 = [(100, 999), (150, 888), (200, 777), (300, 999), (400, 1009), (450, 1019), (500, 1399)]
gas_stations3 = [(101,), (100, 100), (102, 1)]
gas_stations4 = [(34, 1), (105, 9), (9, 10), (134, 66), (215, 90), (999, 1999), (49, 0), (10, 1999), (200, 2), (300, 500), (12, 34), (1, 23), (46, 20), (80, 12), (1, 1999), (90, 33), (101, 23), (34, 88), (103, 0), (1, 1)]
print(solution(500, 4, gas_stations1) == 4300)
print(solution(500, 7, gas_stations2) == 410700)
print(solution(500, 3, gas_stations3) == "Impossible")
print(solution(100, 20, gas_stations4) == 0)
print(solution(100, 0, []) == "Impossible")