LeetCode 2662. Minimum Cost of a Path With Special Roads
周賽343。腦子差點卡死,這題有點繞彎,而且一堆xy有夠麻煩,應該算偏難的Q3。
題目
輸入陣列start = [startX, startY],代表你將從(startX, startY)出發。
還有陣列target = [targetX, targetY],代表目的地(targetX, targetY)。
從(x1, y1)移動到(x2, y2)的成本為|x2 - x1| + |y2 - y1|。
有一些特殊的道路,由二維陣列specialRoads表示,其中specialRoads[i] = [x1i, y1i, x2i, y2i, costi]代表從(x1i, y1i) 到 (x2i, y2i)的成本為costi。
你可以使用各特殊道路任意次。
求從(startX, startY)到(targetX, targetY)的最低成本。
解法
普通移動的成本就是曼哈頓距離。
從起點出發時,你有兩種選擇:
- 直接走到終點
- 先走到某個點,過特殊道路,再到終點
如果後者比前者成本還低,那就代表走這條特殊道路是更佳的。那再繼續判斷有沒有別條路可以繼續省?
發現根本就是dijkstra最短路:優先選成本最低的路徑,第一個到達終點的就是最佳解。
把每個特殊路徑終點的視為節點,共有N個,而可移動的邊共有M=N^2個。
最差情況下每條邊都在heap中,時間複雜度O(M log M),可改寫為O(M log N^2)=O(2*(M log N)),去掉常數變成O(M log N)。
空間複雜度O(M)。
class Solution:
def minimumCost(self, start: List[int], target: List[int], specialRoads: List[List[int]]) -> int:
def dist(x1,y1,x2,y2):
return abs(x1-x2)+abs(y1-y2)
x,y=start
end_x,end_y=target
vis=set()
h=[]
heappush(h,[0,x,y])
while h:
cost,x,y=heappop(h)
if x==end_x and y==end_y:
return cost
if (x,y) in vis:
continue
vis.add((x,y))
# simple move
new_cost=cost+dist(x,y,end_x,end_y)
heappush(h,[new_cost,end_x,end_y])
# use special
for x1,y1,x2,y2,c in specialRoads:
new_cost=cost+dist(x,y,x1,y1)+c
heappush(h,[new_cost,x2,y2])