[Leetcode] Cheapest Flights Within K Stops 計算最便宜票價

Cheapest Flights Within K Stops

There are n cities connected by m flights. Each fight starts from city u and arrives at v with a price w.

Now given all the cities and fights, together with starting city src and the destination dst, your task is to find the cheapest price from src to dst with up to k stops. If there is no such route, output -1.node

Example 1:
Input: n = 3, edges = [[0,1,100],[1,2,100],[0,2,500]] src = 0, dst = 2, k = 1
Output: 200 Explanation: The graph looks like this:
https://s3-lc-upload.s3.amazo...
The cheapest price from city 0 to city 2 with at most 1 stop costs 200, as marked red in the picture.python

Note:數組

The number of nodes n will be in range [1, 100], with nodes labeled from 0 to n - 1.
The size of flights will be in range [0, n * (n - 1) / 2].
The format of each flight will be (src, dst, price).
The price of each flight will be in the range [1, 10000]
k is in the range of [0, n - 1]. There will not be any duplicated flights or self cycles.app

給定一個數組,其中每一個元素表明着從[出發城市,目的城市,飛機票價],如今再給定任意一對不必定有直飛航線的出發城市和目的城市,和最大容許的中轉次數K,求具備最便宜總價的航線組合。this

深度優先搜索

思路

想知道從A到B最便宜的機票組合,只要將全部從A到B在K箇中轉以內的全部路徑組合都遍歷一遍,就能找到最低的價格。然而本題的輸入是城市之間的航線,因此咱們還要先根據這些航線構建一個航線圖。因爲題中說明了不會產生環路,也不會有重複的航線,因此在遍歷圖時不須要檢測環路。code

這裏須要剪枝減小搜索分叉才能經過OJ,剪枝的要點包括:orm

  1. 經過visited集合,記錄當前路徑中已經訪問過的城市,本條路徑中將再也不訪問
  2. 若是當前路徑的距離已經大於以前發現的最短距離,則不用再繼續向下搜索
  3. 中轉次數一旦超過也不須要再向下搜索
class GraphNode:
    def __init__(self, name):
        self.name = name
        self.dsts = []
    
    def addFlight(self, dst, price):
        self.dsts.append((dst, price))
        

class Solution:
    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
        """
        flightsMap = self.constructGraph(flights)
        self.globalMin = float('inf')
        self.findFlight(flightsMap, flightsMap.get(src), 0, dst, 0, K, set())
        return -1 if self.globalMin == float('inf') else self.globalMin
        
    def findFlight(self, flightsMap, node, totalPrice, finalDst, stops, stopLimit, visited):
        if node is None or stops > stopLimit:
            return
        if self.globalMin < totalPrice:
            return
        for dst in node.dsts:
            dstName, dstPrice = dst
            nextTotalPrice = dstPrice + totalPrice
            if dstName == finalDst: # 若是找到目的地,則計算當前的距離並和最小值比較
                self.globalMin = min(self.globalMin, nextTotalPrice)
            elif flightsMap.get(dstName) is not None and self.globalMin > nextTotalPrice and dstName not in visited: # 若是不是目的地,則繼續向下找,這裏中轉次數要加一,而且本條路徑中已經訪問過的節點不用再訪問
                visited.add(dstName)
                self.findFlight(flightsMap, flightsMap.get(dstName), nextTotalPrice, finalDst, stops + 1, stopLimit, visited)
                visited.remove(dstName)

    def constructGraph(self, flights):
        flightsMap = {}
        for flight in flights: # 將航線按照出發城市一一加入圖中
            src = flight[0]
            dst = flight[1]
            price = flight[2]
            node = flightsMap.get(src, GraphNode(src))
            node.addFlight(dst, price)
            flightsMap[src] = node
        return flightsMap
相關文章
相關標籤/搜索