K 站中转内最便宜的航班

这篇博客介绍了如何利用改进的BFS(优先级队列)和DFS(回溯)解决LeetCode 787题,即找到在限制中转次数内的最便宜航班。博主分析了两种方法的实现细节,并指出它们在某些情况下可能超时。此外,还提及了贝尔曼-福特算法作为另一种可能的解决方案。
摘要由CSDN通过智能技术生成

leetcode 787 K站中转内最便宜的航班
这一题是带有限制的带权最短路径题目。

方法一:改进的BFS,使用优先级队列(超时)

一般遇到最短路径(最少步骤、最近距离)的题目,要下意识地想到用BFS。

这一题是带权的,直接bfs不好写,可以借助于优先级队列,这一题中需要用到小根堆,每次选择距离src最近的进行处理

class Node{
public:
    int N;  //号
    int K;  //与src之间有多少个中转节点
    int D;  //与src之间的距离
    Node(int n,int k,int d):N(n),K(k),D(d){}
    bool operator<(const Node &node)const{
        return D>node.D;    //小根堆
    }
};

class Solution {
public:
    int findCheapestPrice(int n, vector<vector<int>>& flights, int src, int dst, int k) {
        vector<vector<int>>edges(n,vector<int>(n,-1));
        for(auto&a:flights){
            edges[a[0]][a[1]]=a[2];
        }
        priority_queue<Node>que;
        que.push(Node(src,-1,0));
        while(!que.empty()){
            Node first=que.top();
            que.pop();
            if(first.N==dst && first.K<=k){
                return first.D;
            }
            if(first.K>=k)
                continue;
            //将后续放入
            for(int i=0;i<n;i++){
                if(edges[first.N][i]!=-1){
                    que.push(Node(i,first.K+1,first.D+edges[first.N][i]));
                }
            }      
        }
        return -1;
    }
};

注意:在这一题中,某些用例下会超时。

方法二:dfs+回溯+剪枝(超时)

class Solution {
public:
    int des,n;
    vector<vector<int>>edge;
    int findCheapestPrice(int n, vector<vector<int>>& flights, int src, int dst, int k) {
        //邻接矩阵
        edge=vector<vector<int>>(n,vector<int>(n,0x3f3f3f3f));
        for(auto&a:flights){
            edge[a[0]][a[1]]=a[2];
        }
        des=dst;
        this->n=n;
        int ans=help(src,k);
        return ans!=0x3f3f3f3f?ans:-1;
    }
    //src节点,在k个中转限制下到达终点,所需的最小费用(如果不能则返回0x3f3f3f3f)
    int help(int src,int k){
        //k不可能满足了
        if(k<-1)
            return 0x3f3f3f3f;
        //走到终点
        if(src==des){
            return k>=-1?0:0x3f3f3f3f;
        }
        int ans=0x3f3f3f3f;
        //寻找下一个节点
        for(int i=0;i<n;i++){
            if(edge[src][i]!=0x3f3f3f3f && edge[src][i]<ans){
                ans=min(ans,edge[src][i]+help(i,k-1));
            }
        }
        path.erase(src);
        return ans;
    }
};

方法四:Bellman-Ford 算法

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值