787. Cheapest Flights Within K Stops
題目:
There are n cities connected by some number of flights. You are given an array flights
where flights[i] = [fromi, toi, pricei]
indicates that there is a flight from city fromi
to city toi
with cost pricei
.
You are also given three integers src
, dst
, and k
, return the cheapest price from src
to dst
with at most k
stops. If there is no such route, return -1
.
Image Not Showing
Possible Reasons
- The image file may be corrupted
- The server hosting the image is unavailable
- The image path is incorrect
- The image format is not supported
Learn More →
Image Not Showing
Possible Reasons
- The image file may be corrupted
- The server hosting the image is unavailable
- The image path is incorrect
- The image format is not supported
Learn More →
Image Not Showing
Possible Reasons
- The image file may be corrupted
- The server hosting the image is unavailable
- The image path is incorrect
- The image format is not supported
Learn More →
解題想法:
- 此題為求從src到dst的最少需要花多少錢,最多可以中轉k個休息站。
- 因為k=1,代表可以有一個休息站
- 走A->B->C,可視為走k+1步
法1: graph
-
Dijkstra: 指定一點到其餘各點的最短路徑
- 正常Dijkstra為greedy,紀錄每點是否已拜訪過並逐一取出最小權重更新
- 但此題為變化,需利用k步判斷,所以就不採用額外visited數組紀錄每點是否已經拜訪過
- 改用字典紀錄起始點與已走幾步作為拜訪依據
- dic=defaultdict(lambda: float('inf'))
- key:(src到其他位置,經由幾步到達)
- val:cost
- 補充知識,defaultdict的默認值: item=defaultdict(lambda: "預設")
-
編寫流程:
- use binary heap: time: O((|e|+|v|)logV)
- Step1: 建立邊
- Step3-1: while迴圈每次pop出que中權重最小的
Python:
from collections import defaultdict
from heapq import heappush, heappop
class Solution(object):
def findCheapestPrice(self, n, flights, src, dst, k):
"""
:type n: int
:type flights: List[List[int]]
:type src: int
:type dst: int
:type k: int
:rtype: int
"""
edge=defaultdict(list)
for u,v,w in flights:
edge[u].append((v,w))
dic=defaultdict(lambda: float('inf'))
que=[(0, src, 0)]
while que:
cost, curPos, step=heappop(que)
if step>k+1:
continue
if curPos==dst:
return cost
for neighber, weight in edge[curPos]:
tmpCost=cost+weight
if tmpCost<dic[(neighber,step+1)]:
heappush(que, (tmpCost, neighber, step+1))
dic[(neighber, step+1)]=tmpCost
return -1
if __name__=='__main__':
n =5
flights =[[0,1,5],[1,2,5],[0,3,2],[3,1,2],[1,4,1],[4,2,1]]
src =0
dst =2
k =2
result=Solution()
ans=result.findCheapestPrice(n,flights,src,dst,k)
print(ans)
法2: 使用Dynamic Programming
- Bellman Ford
- dp[i][j]: 從起始位置,走i步能到達j位置的最低價格
- 初始:
- dp[i][src]=0 (i=0~k+1): 起始位置走i步到起始位置,cost=0
- 轉移方程式:
- 對於每組flights=[curPos, Neighber, weight]
- 每次更新鄰居:
- 對於走i步能到達neighber :dp[i][neighber]
- dp[i][neighber]=min(原本走i步能到達neighber or 走i-1步達到當前位置curPos,再加上curPos到neighber的weight)
- dp[i][neighber]=min(dp[i][neighber], dp[i-1][curPos]+weight)
C++: