【力扣roadmap】2662. 前往目标的最小代价

0 阅读2分钟

题目描述

image.png

思路分析

首先要清楚的是,给出的特殊路径中起点并不重要,重要的是这些特殊路径的终点。

我们将起点,特殊路径终点,终点,建模成图。(无需刻意建图)

然后跑dijkstra求最短路算法即可。

1、 我们需要dist数组(这里使用dict代替)存储当前起点到各点的最短路,算法结束后dist存储了起点到所有点的最短路

2、 优先队列存储当前不确定最短路的点,每次从队首弹出的元素是当前所有不确定最短路的点中距离起点最近的。但是从队首弹出的元素可能是早已经更新过的,所以...

3、 我们需要vis集合,用于对优先队列弹出的元素进行判重。

用从队首弹出的元素(x,y)对其他点(x2,y2)进行更新的方式: 1、 从(x,y)直接到(x2,y2) 2、 从(x,y)经过(x1,y1)使用特殊路径达到(x2,y2)

算法结束后,返回dist[target]作为答案。

代码

class Solution:
    def minimumCost(self, start: List[int], target: List[int], specialRoads: List[List[int]]) -> int:
        sx,sy = start
        tx,ty = target
        def manh(a,b,x,y):
            return abs(a-x) + abs(b-y) 
        roads = []
        for x1,y1,x2,y2,sd in specialRoads:
            c = manh(x1,y1,x2,y2) 
            roads.append((x1,y1,x2,y2,min(c,sd)))
        roads.append((sx,sy,tx,ty,manh(sx,sy,tx,ty)))
        vis = set() 
        dist = {(sx,sy):0}
        pq = [(0,sx,sy)] 
        while pq : 
            d,x,y = heappop(pq)
            if (x,y) in vis :
                continue 
            vis.add((x,y)) 
            for x1,y1,x2,y2,c in roads:
                # 从(x,y)有两个方法到达当前有向线段终点:
                # 1. 从(x,y)直接过去
                # 2. 从(x,y)先到有向线段起点利用特殊路径过去
                to_seg_end = min(d + manh(x,y,x2,y2) , d + manh(x,y,x1,y1) + c ) 
                if to_seg_end < dist.get((x2,y2),float('inf')) :
                    dist[(x2,y2)] = to_seg_end 
                    heappush(pq,(to_seg_end,x2,y2)) 
        return dist[(tx,ty)]