刷题之-“优化青海湖至景点X的租车路线成本” | 豆包MarsCode AI刷题

53 阅读6分钟

问题描述

小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

题目解析

本题旨在解决从青海湖前往特定景点 X 的旅行中,通过合理规划在沿途加油站的加油顺序与数量,以最小化燃油成本的问题。关键信息包括:车辆油箱容量、起始油量、每公里耗油量、到景点的距离、沿途加油站数量及各站信息(距离起始点与油价),且还车时需保证车内至少剩余 200L 油。

思路分析

1. 数据预处理:首先对加油站信息按照距离起始点的位置升序排序,方便后续按顺序处理。同时计算相邻加油站之间的距离,为后续计算油量消耗与成本做准备。 2. 动态规划求解:

  • 定义状态:使用二维数组 dp,其中 dp[i][j] 表示到达第 i 个加油站且油箱剩余油量为 j 时的最小花费。
  • 状态转移:对于每个加油站 i,遍历前一个加油站可能的剩余油量 k。如果从 k 油量能到达当前加油站且满足各种油量限制条件,就更新 dp[i][j],即考虑在当前加油站加油量为 j + dis[i - 1] - k 时的花费 dp[i - 1][k] 加上本次加油的成本 (j + dis[i - 1] - k) * gasStations[i - 1][1],取最小值作为 dp[i][j]。 3. 判断结果:计算到达终点后剩余的油量,若超出油箱容量或为负数则无法完成任务。否则,在满足还车油量要求的前提下,从 dp 数组中找到到达最后一个加油站时的最小花费作为最终结果。

代码展示

 import sys

def solution(distance, n, gasStations):
     maxCapacity = 400
     inf = sys.maxsize

# 按照加油站位置升序排序
gasStations.sort(key=lambda x: x[0])

# 计算每个加油站之间的距离
dis = [gasStations[0][0]]
    for i in range(1, len(gasStations)):
       dis.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 j + dis[i-1] - k >= 0 and k >= dis[i-1]:
                dp[i][j] = min(dp[i][j], dp[i-1][k] + (j + dis[i-1] - k) * gasStations[i-1][1])

# 判断是否可以到达终点
remaining_fuel = 200 + distance - gasStations[n-1][0]

if remaining_fuel > maxCapacity or remaining_fuel < 0:
    return -1

result = inf
for i in range(remaining_fuel, maxCapacity + 1):
    result = min(result, dp[n][i])

if result == inf:
    return -1

return result

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)

知识总结

1. 动态规划:本题是典型的动态规划应用,通过定义合适的状态和状态转移方程来求解最优解。关键在于确定状态的表示以及如何从前面的状态推导出当前状态的最优值。 2. 排序与数据处理:对加油站数据的排序以及计算距离等预处理操作,有助于简化后续的逻辑处理,提高算法效率。 3. 边界条件处理:在动态规划过程中以及最后判断能否到达终点并满足还车要求时,都需要仔细考虑各种边界条件,如油量不能为负、不能超过油箱容量等。

学习心得

通过解决本题,深刻体会到动态规划在解决复杂优化问题中的强大作用。在分析问题时,要善于提取关键信息,构建合适的数学模型。同时,对于数据的预处理和边界条件的把控至关重要,一个小的疏忽可能导致结果错误。在编写代码过程中,要注重代码的规范性和可读性,合理使用数据结构和算法技巧,提高代码效率。此外,多做此类题目有助于提升逻辑思维能力和编程能力,遇到问题时要冷静思考,逐步分析,不断积累经验,才能更好地应对各种算法挑战。