787. K 站中转内最便宜的航班

方法一:递归

class Solution:    
    def findCheapestPrice(self, n: int, flights: List[List[int]], src: int, dst: int, k: int) -> int:     
        sdp = defaultdict(list)        
        for s,d,p in flights:
            sdp[s].append([d,p])

        @lru_cache(None)
        def dfs(c, t):           
            if c == dst: return 0  # c 就是目标城市,票价为 0            
            if t > k: return inf # 中转次数 t > k 不可达               
            ans = inf
            for d,p in sdp[c]:                
                ans = min(ans, dfs(d,t+1) + p)
            
            return ans
        
        res = dfs(src, 0)
        return res if res != inf else -1

方法二:记忆化搜索

class Solution:    
    def findCheapestPrice(self, n: int, flights: List[List[int]], src: int, dst: int, k: int) -> int:     
        sdp = defaultdict(list)        
        for s,d,p in flights:
            sdp[s].append([d,p])

        # @lru_cache(None)
        def dfs(c, t):
            if c == dst: return 0
            if t > k: return inf    
            if memo[c][t]: return memo[c][t]
            ans = inf
            for d,p in sdp[c]:                
                ans = min(ans, dfs(d,t+1) + p)
            memo[c][t] = ans
            return ans
        memo = [[0]*(k+1) for _ in range(n)]
        res = dfs(src, 0)
        return res if res != inf else -1

方法三:动态规划

787. K 站中转内最便宜的航班_python 表示从城市 787. K 站中转内最便宜的航班_一维数组_02 出发,经过 787. K 站中转内最便宜的航班_List_03 次航班(787. K 站中转内最便宜的航班_python_04 中转),到达城市 787. K 站中转内最便宜的航班_一维数组_05 所需的最少花费。枚举直达 787. K 站中转内最便宜的航班_一维数组_05787. K 站中转内最便宜的航班_python_07,那么前 787. K 站中转内最便宜的航班_python_04 次航班到达 787. K 站中转内最便宜的航班_python_07 的花费 787. K 站中转内最便宜的航班_一维数组_10 加上最后一次航班的花费 787. K 站中转内最便宜的航班_一维数组_11 中的最小值,即为 787. K 站中转内最便宜的航班_python

即:

787. K 站中转内最便宜的航班_一维数组_13

其中 787. K 站中转内最便宜的航班_状态转移_14 表示从城市 787. K 站中转内最便宜的航班_python_07 到达城市 787. K 站中转内最便宜的航班_一维数组_05 的航班,787. K 站中转内最便宜的航班_一维数组_11

由于最多中转 787. K 站中转内最便宜的航班_List_18

787. K 站中转内最便宜的航班_状态转移_19

中的最小值。

787. K 站中转内最便宜的航班_状态转移_20

注意到 787. K 站中转内最便宜的航班_python 只会从 787. K 站中转内最便宜的航班_状态转移_22

下面的代码使用二维数组进行状态转移。

class Solution:    
    def findCheapestPrice(self, n: int, flights: List[List[int]], src: int, dst: int, k: int) -> int:       
        f = [[inf] * n for _ in range(k+2)]
        f[0][src] = 0
        for t in range(1, k+2):
            for s, d, cost in flights:
                f[t][d] = min(f[t][d], f[t-1][s] + cost)
        
        ans = min(f[t][dst] for t in range(1, k+2))
        return -1 if ans == inf else ans

下面的代码使用两个一维数组进行状态转移。

class Solution:    
    def findCheapestPrice(self, n: int, flights: List[List[int]], src: int, dst: int, k: int) -> int:       
        f = [inf] * n
        f[src] = 0
        ans = inf
        for t in range(1, k + 2):
            g = [inf] * n
            for s, d, cost in flights:
                g[d] = min(g[d], f[s] + cost)
            f = g
            ans = min(ans, f[dst])
        
        return -1 if ans == inf else ans