伴学笔记第四篇 | 豆包MarsCode AI 刷题

114 阅读4分钟

优化青海湖至景点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. 每个加油站有不同的油价,我们需要选择性地加油以最小化费用。
  2. 从起点出发到达终点,油量必须在每个阶段都充足。每次加油要考虑油量是否足够到达下一个加油站或目标。
  3. 油量和加油站的选择之间存在相互依赖关系,需要在加油时合理选择,避免过多浪费和不必要的开销。
  4. 最小化总油费,且终点到达时油量不能低于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]  # 返回最小油费

代码解析

  1. 加油站排序:首先将所有加油站按距离从起点的顺序排序,确保每次计算时能够按照顺序遍历加油站。
  2. 计算距离:然后,计算相邻加油站之间的距离,便于后续计算油量消耗。
  3. 动态规划表初始化:创建一个动态规划表dp,其中dp[i][j]表示在第i个加油站时油量为j时的最小花费。初始状态为dp[0][200] = 0,表示从起点出发,油量为200L时花费为0。
  4. 状态转移:遍历所有加油站,并根据油量的变化更新动态规划表。在每次转移时,计算到达某个加油站的油量,并更新最小花费。
  5. 最终判断:如果无法到达终点,返回-1;否则,返回最小油费。

时间复杂度

动态规划的时间复杂度为O(n * 401 * 401),其中n为加油站的数量。由于每个加油站需要遍历所有可能的油量状态(最大为400L),并且每个状态的转移需要遍历前一个加油站的所有可能油量。