青海湖租车路线成本 | 豆包MarsCode AI刷题

106 阅读5分钟

问题描述

小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试一下算了

数据结构选择

  1. 加油站信息

    • 使用一个列表 gasStations 存储每个加油站的信息,每个元素是一个包含两个整数的元组 (距离, 油价)
  2. 动态规划数组

    • 使用一个二维数组 dp,其中 dp[i][j] 表示到达第 i 个加油站时,油箱剩余油量为 j 时的最小花费。

算法步骤

  1. 初始化

    • 将 gasStations 按照距离升序排序。
    • 初始化 dp 数组,dp[0][200] = 0,表示在起点(青海湖)时,油箱剩余200L,花费为0。
  2. 动态规划计算

    • 对于每个加油站 i,计算从上一个加油站到当前加油站的距离 distances[i-1]
    • 对于每个可能的油量 j,计算从上一个加油站到当前加油站的最小花费。
    • 更新 dp[i][j],确保在当前加油站加油后,油量不超过400L,且花费最小。
  3. 判断是否可以到达终点

    • 计算到达终点时的剩余油量 remaining_fuel_at_destination
    • 如果剩余油量超过400L或小于0,返回 -1
  4. 计算最小花费

    • 遍历 dp[n][i],找到到达终点时的最小花费。
  5. 时间复杂度

    • 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")