• 算法学习--Day9


    继上一次完成最小生成树后,这次我开始准备最短路径的程序。

    最短路分为两种算法,第一个为Floyd算法,第二个为Dijkstra。

    简单来说,Floyd是以点为参照对象,它使用三层循环求解当前图中所有点之间的最短距离。

    也就是说,当他的循环处理结束后,你就可以从中找到任意两点之间的最短路径了。

    他将大规模问题简化成为若干个子问题,并先对规模小的问题求解出最优值,之后利用规模小的问题的解去递推出大规模问题的解。

    核心代码:

    for(int i=1;i<=n;i++){
        for(int j=1;j<=n;j++){
            for(int k=1;k<=n;k++){
               if(ans[j][i]==-1 || ans[i][k]==-1) continue;
    //这句话说明倘若我j-i-k中间有某条路是不通的,这个时候我就不能被更新,所以直接跳过就好
               if(ans[j][k]==-1 || ans[j][i]+ans[i][k]<ans[j][k]){  ans[j][k]= ans[j][i]+ans[i][k];}
    //这句话用来更新最小值
    }    
    }
    }         

    下面我们看dijkstra算法。

    题目描述

    给你n个点,m条无向边,每条边都有长度d和花费p,给你起点s终点t,要求输出起点到终点的最短距离及其花费,如果最短距离有多条路线,则输出花费最少的。

    输入描述:

    输入n,m,点的编号是1~n,然后是m行,每行4个数 a,b,d,p,表示a和b之间有一条边,且其长度为d,花费为p。最后一行是两个数 s,t;起点s,终点t。n和m为0时输入结束。
    (1<n<=1000, 0<m<100000, s != t)

    输出描述:

    输出 一行有两个数, 最短距离及其花费。
    示例1

    输入

    复制
    3 2
    1 2 5 6
    2 3 4 5
    1 3
    0 0
    

    输出

    复制
    9 11
    //
    // Created by 陈平 on 2018/6/7.
    //
    
    #include "iostream"
    #include "stdio.h"
    #include "vector"
    using namespace std;
    
    struct E{
        int next;
        int c;
        int cost;
    
    };
    vector<E> edge[1001];
    int dis[1001];
    int cost[1001];
    bool mark[1001];
    int main(){
        int n,m;
        int s,t;
        while (scanf("%d%d",&n,&m)!=EOF){
            if(n==0 && m==n) break;
            for (int i = 1; i <=n ; ++i) {
                edge[i].clear();
            }
            while (m--){
                int a,b,c,cost;
                cin>>a>>b>>c>>cost;
                E tmp;
                tmp.c = c;
                tmp.cost = cost;
                tmp.next = b;
                edge[a].push_back(tmp);
                tmp.next = a;
                edge[b].push_back(tmp);
            }
            cin>>s>>t;
            for (int j = 1; j <=n ; ++j) {
                dis[j] = -1;
                mark[j] = false;
            }
            dis[s] = 0;
            cost[s] = 0;
            mark[s] = true;
            int newP = s;
    
    
            for (int k = 1; k <n ; ++k) {
                for (int i = 0; i <edge[newP].size() ; ++i) {
    
                    int t = edge[newP][i].next;
                    int c = edge[newP][i].c;
                    int co = edge[newP][i].cost;
                    if(mark[t]) continue;
                    if (dis[t]==-1 || dis[t]>dis[newP] + c ||dis[t]==dis[newP] + c && cost[t]>cost[newP]+co ){
                        dis[t] = dis[newP] + c;
                        cost[t] = cost[newP] + co;
                    }
                }
    
                int minn = 1000000;
                for (int j = 1; j <=n ; ++j) {
    
                    if(mark[j]) continue;
                    if(dis[j]==-1) continue;
                    if(dis[j] < minn ){
    
                        minn = dis[j];
                        newP = j;
    
                    }
                }
                mark[newP] = true;
            }
    
        cout<<dis[t]<<" "<<cost[t]<<endl;
        }
    }

    在写最短路的时候,我们要熟悉使用链表的写法,当数据量增多的时候,使用链表会使节省空间与时间。所以我们要在初始化的时候使用push_back函数把值push进去。而在处理的时候,我们需要分两步去找最优解。第一步为更新当前点集合所连接的点的长度数据。(因为上一步加入了另一个点后我们的长度还未更新)第二步为寻找未在当前集合并且是最短距离的点。(具体流程见我之前的一个博客——https://www.cnblogs.com/Pinging/p/7911169.html

  • 相关阅读:
    快排笔记C++
    security+redis+jwt 一个登陆注册查询的例子
    centeros 配置好环境虚拟机下载(java git mysql maven nginx Python redis nodejs tomcat )
    ZwQueryInformationProcess 反调试代码
    c++ 创建进程设置窗口标题模拟键盘鼠标例子
    求一个数二进制中包含多少个1
    憨批是我
    憨批是我
    问卷星实现自动填表刷问卷(问卷星分析post协议实现 安卓版)
    前端面试题 -- 综合
  • 原文地址:https://www.cnblogs.com/Pinging/p/9158775.html
Copyright © 2020-2023  润新知