来自北大算法课的Leetcode题解:787. K站中转内最便宜的航班

代码仓库Github | Leetcode solutions @doubleZ0108 from Peking University.

  • 解法1(超时):图的广搜。外层通过queue广搜,弹出一个节点遍历图中所有起始点为此弹出node的边,如果这条边的dst就是终点则添加到可能结果中(实现时只保存最小的价格就好),如果不是终点就把dst作为新的src入队,并让其搜索层次+1,如果发现某次出对已经是k次中转之外的就可以提前返回了

    • 改进1(超时):猜想应该是重复查找耗时,因此首先将图表示为邻接矩阵,这样每次遍历只需遍历一行
    • 改进2(会出错):把遍历过的(src,dst)对存在visited防止重复遍历,但从不同的路径遍历来很可能价钱不一样的,这样会无法得到最优解
    • 改进3(超时): 把邻接矩阵换成邻接表,还是会有太多没意义的中转入队
    • 改进4(超时): 也像递归方法一样加入memo,能通过刚刚超时的例子了,但更大的还是会超时
  • 解法2(T5% S54%):还是广搜,只是用递归实现,这样可以加入memo。memo的设计很巧妙,并不是存储某个src到某个dst的过往值,而是存某个src到最终目标的当前最小价格。递归终止条件为:轮次用完了 or 走到目标了 or memo在这个起点和轮次恰好能走到最终目标,如果没终止则依次遍历航班信息bfs搜索当前价格并刷新最小价格,最后将最小价格存下来并返回

  • 解法3: 动态规划,将每两点的连接矩阵不断更新(更新K步 or 两次更新不再改变)

class Solution:
    def findCheapestPrice(self, n: int, flights, src: int, dst: int, k: int) -> int:
        INF = 1e06+1
        memo = [[-1]*(k+1) for _ in range(n)]

        def bfs(thisstr, turn):
            if turn < -1: return INF
            if thisstr == dst: return 0
            if memo[thisstr][turn]!=-1: return memo[thisstr][turn]

            minPrice = INF
            for flight in flights:
                if flight[0] == thisstr:
                    thisprice = bfs(flight[1], turn-1)+flight[2]
                    minPrice = min(minPrice, thisprice)

            memo[thisstr][turn] = minPrice
            return minPrice

        res = bfs(src, k)
        return res if res<INF else -1


    def otherSolution(self, n, flights, src, dst, k):
        INF = 1e06+1

        queue = [(src, 0, 0)]   # 当前扩展到的节点,到目前为止的轮次,到目前为止的总价格
        minPrice = INF
        memo = [[-1]*(k+1) for _ in range(n)]

        while queue:
            node, turn, price = queue.pop(0)
            if turn > k: break

            if memo[node][k-turn] != -1:
                minPrice = min(minPrice, memo[node][k-turn]+price)
                continue

            for flight in flights:
                if flight[0] == node:
                    thisdst, thisprice = flight[1], flight[2]
                    if thisdst == dst:  
                        thisprice += price
                        minPrice = min(minPrice, thisprice)
                        memo[node][turn] = thisprice
                    else:
                        if memo[thisdst][k-turn-1] != -1:
                            minPrice = min(minPrice, memo[thisdst][k-turn-1])
                        else:
                            queue.append((thisdst, turn+1, thisprice+price))


        return minPrice if minPrice != INF else -1
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

doubleZ0108

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值