• 7-10 旅游规划 (25 分)


    7-10 旅游规划 (25 分)

    有了一张自驾旅游路线图,你会知道城市间的高速公路长度、以及该公路要收取的过路费。现在需要你写一个程序,帮助前来咨询的游客找一条出发地和目的地之间的最短路径。如果有若干条路径都是最短的,那么需要输出最便宜的一条路径。

    输入格式:

    输入说明:输入数据的第1行给出4个正整数N、M、S、D,其中N(2N500)是城市的个数,顺便假设城市的编号为0~(N1);M是高速公路的条数;S是出发地的城市编号;D是目的地的城市编号。随后的M行中,每行给出一条高速公路的信息,分别是:城市1、城市2、高速公路长度、收费额,中间用空格分开,数字均为整数且不超过500。输入保证解的存在。

    输出格式:

    在一行里输出路径的长度和收费总额,数字间以空格分隔,输出结尾不能有多余空格。

    输入样例:

    4 5 0 3
    0 1 1 20
    1 3 2 30
    0 3 4 10
    0 2 2 20
    2 3 1 20
    

    输出样例:

    3 40
    Dijkstra算法
    
    1.定义概览
    
    Dijkstra(迪杰斯特拉)算法是典型的单源最短路径算法,用于计算一个节点到其他所有节点的最短路径。主要特点是以起始点为中心向外层层扩展,直到扩展到终点为止。Dijkstra算法是很有代表性的最短路径算法,在很多专业课程中都作为基本内容有详细的介绍,如数据结构,图论,运筹学等等。注意该算法要求图中不存在负权边。
    
    问题描述:在无向图 G=(V,E) 中,假设每条边 E[i] 的长度为 w[i],找到由顶点 V0 到其余各点的最短路径。(单源最短路径)
    
     
    
    2.算法描述
    
    1)算法思想:设G=(V,E)是一个带权有向图,把图中顶点集合V分成两组,第一组为已求出最短路径的顶点集合(用S表示,初始时S中只有一个源点,以后每求得一条最短路径 , 就将加入到集合S中,直到全部顶点都加入到S中,算法就结束了),第二组为其余未确定最短路径的顶点集合(用U表示),按最短路径长度的递增次序依次把第二组的顶点加入S中。在加入的过程中,总保持从源点v到S中各顶点的最短路径长度不大于从源点v到U中任何顶点的最短路径长度。此外,每个顶点对应一个距离,S中的顶点的距离就是从v到此顶点的最短路径长度,U中的顶点的距离,是从v到此顶点只包括S中的顶点为中间顶点的当前最短路径长度。
    
    (1) 初始时,S只包含起点s;U包含除s外的其他顶点,且U中顶点的距离为"起点s到该顶点的距离"[例如,U中顶点v的距离为(s,v)的长度,然后s和v不相邻,则v的距离为∞]。
    
    (2) 从U中选出"距离最短的顶点k",并将顶点k加入到S中;同时,从U中移除顶点k。
    
    (3) 更新U中各个顶点到起点s的距离。之所以更新U中顶点的距离,是由于上一步中确定了k是求出最短路径的顶点,从而可以利用k来更新其它顶点的距离;例如,(s,v)的距离可能大于(s,k)+(k,v)的距离。
    
    (4) 重复步骤(2)和(3),直到遍历完所有顶点。
    #include<iostream>
    #include<stdio.h>
    using namespace std;
    //距离表
    struct
    {
        int visit;
        int len;
        int cost;
    }Visit[510];
    //路线图
    struct
    {
        int len;
        int cost;
    }Graph[510][510];
    //初始化路线图,长度和过路费全初始化为999,相当于无穷
    void InitGraph(int N)
    {
        for(int i=0; i<=N; i++)
            for(int j=0; j<=N; j++){
                Graph[i][j].len = 999;
                Graph[i][j].cost = 999;
            }
    }
    //根据输入的路线图初始化距离表
    //并且初始化源地到源地的距离和路费均为0
    void InitVisit(int N, int S)
    {
        for(int i=0; i<=N; i++){
            Visit[i].visit = 0;
            Visit[i].len = Graph[i][S].len;
            Visit[i].cost = Graph[i][S].cost;
        }
        Visit[S].visit = 1;
        Visit[S].cost = 0;
        Visit[S].len = 0;
    }
    //利用Dijkstra(迪杰斯特拉)算法计算源地到各地的距离最短
    int DKS(int N, int S)
    {
        //循环 N-1 次找到这N-1个点到源点的距离最短
        for(int j=1; j<N; j++){
            //先找到一个距离最短的点
            int MinPoint=N;//第N+1个点的距离已设置为999,相当于无穷
            for(int i=0; i<N; i++){
                if(!Visit[i].visit&&Visit[i].len<Visit[MinPoint].len){
                    MinPoint = i;
                }
            }
            if(MinPoint == N)//没找到最短点,也就是完成循环,退出,可省略
                break;
            Visit[MinPoint].visit = 1;
            for(int i=0; i<N; i++){
                   if(!Visit[i].visit){
                      //原点->中继点->终点 < 原点->终点,更新最短距离
                      if(Visit[i].len>Visit[MinPoint].len+Graph[i][MinPoint].len){
                        Visit[i].len = Visit[MinPoint].len+Graph[i][MinPoint].len;
                        Visit[i].cost = Visit[MinPoint].cost+Graph[i][MinPoint].cost;
                      }
                      //距离相同找花费更小的
                      if(Visit[i].len==Visit[MinPoint].len+Graph[i][MinPoint].len){
                        if(Visit[i].cost>Visit[MinPoint].cost+Graph[i][MinPoint].cost)
                        Visit[i].cost=Visit[MinPoint].cost+Graph[i][MinPoint].cost;
                      }
                   }
            }
        }
    
    }
    int main()
    {
        int N, M, S, D;
        cin>>N>>M>>S>>D;
        InitGraph(N);
        int c1, c2, l, m;
        for(int i=0; i<M; i++){
            cin>>c1>>c2>>l>>m;
            Graph[c1][c2].len = l;
            Graph[c1][c2].cost = m;
            Graph[c2][c1].len = l;
            Graph[c2][c1].cost = m;
        }
        InitVisit(N, S);
        DKS(N, S);
        cout<<Visit[D].len<<" "<<Visit[D].cost;
    }
  • 相关阅读:
    wpf学习笔记StackPanel
    wpf学习笔记DockPanel
    wpf学习笔记Viewbox
    C#.NET 中的类型转换
    超简单U盘PE启动完全攻略(U盘上仅四个文件)
    Web 应用的 UML 建模与 .NET 框架开发
    100多个很有用的JavaScript函数以及基础写法大集合
    Asp.net(C#)显示所有缓存 清除所有缓存
    grub引导U盘(集成常用工具/深山红叶PE工具箱V30/完美者U盘维护系统V8.1)
    GRUB启动命令详解
  • 原文地址:https://www.cnblogs.com/Jie-Fei/p/9873419.html
Copyright © 2020-2023  润新知