• 7-9 旅游规划(25 分)(Dijkstra最短路径算法)


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

    输入格式:

    输入说明:输入数据的第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

    解题思路:1、很明显这是一个图的问题,但是它有两个权值,因而我用了一个三元数组来存储数据

                      2、又因其是单源最短路径,因而使用Dijkstra算法

                      3、其次注意一下如果最短距离相同还要判断费用是否最小

                     4、最后还要小心0也算是一个城市

      1 #include<stdio.h>
      2 #include<stdlib.h>
      3 
      4 #define MAXVEX 505
      5 #define INFINITY  65535
      6 
      7 void CreateGraph( );
      8 void Dijkstra( int v);
      9 
     10 
     11 int G[MAXVEX][MAXVEX][2],Nv,Ne;
     12 int know[MAXVEX];        //know[]=1表示求得最短路径
     13 int distance[MAXVEX];   //表示求的最短距离
     14 int pay[MAXVEX];       //表示最少费用
     15 //int P[MAXVEX];        //存储最短路径的下标
     16 
     17 int main()
     18 {
     19     int s,d;
     20     scanf("%d %d %d %d",&Nv,&Ne,&s,&d);
     21     CreateGraph();
     22     Dijkstra(s);
     23     if( distance[d]<INFINITY ){
     24         printf("%d %d",distance[d],pay[d]);
     25     }
     26        
     27     return 0;
     28 }
     29 
     30 void CreateGraph()
     31 {
     32     //用邻接矩阵表示图
     33     int i,j;
     34     int v1,v2;
     35     int dn,f;  //dn表示距离,f表示费用
     36 
     37     for( i=0; i<Nv; i++)
     38     {
     39         for( j=0; j<Nv; j++)
     40         {
     41             G[i][j][0] = INFINITY;  //初始化
     42             G[i][j][1] = INFINITY;
     43         }
     44     }
     45 
     46     for( i=0; i<Ne; i++)  //注意这里是读入边
     47     {
     48         scanf("%d %d %d %d",&v1,&v2,&dn,&f);
     49         G[v1][v2][0] = G[v2][v1][0]=dn;
     50         G[v1][v2][1] = G[v2][v1][1]=f;
     51     }
     52 }
     53 
     54 void Dijkstra( int v)
     55 {
     56     //求从v结点到其他各结点的最短距离
     57     int i,j,k;
     58     int min,cost;
     59 
     60     for( i=0; i<Nv; i++)
     61     {
     62         know[i] =0;
     63         distance[i] =G[v][i][0];   //将与v点有连接的结点加上距离
     64         pay[i] =G[v][i][1];
     65     }
     66 
     67     know[v] = 1;
     68     distance[v] =0;   //V到V距离为0
     69     pay[v] = 0;
     70 
     71     for( i=1; i<Nv; i++)
     72     {
     73         min = INFINITY;     //当前所知离v结点的最近距离
     74         for( j=0; j<Nv; j++)
     75         {
     76             //寻找离v结点的最近距离
     77             if( !know[j] && distance[j]<min)
     78             {
     79                 k = j;
     80                 min = distance[j];
     81                 cost = pay[j];
     82             }
     83         }
     84 
     85         know[k] = 1;
     86         for( j=0; j<Nv; j++)
     87         {
     88             //修正最短路径和距离
     89             if( !know[j] && (min+G[k][j][0]<distance[j]))
     90             {
     91                 distance[j] = min+G[k][j][0];
     92                 pay[j] = cost + G[k][j][1];
     93 
     94             }
     95             else if( !know[j] && (min+G[k][j][0]==distance[j]) && (cost+G[k][j][1] < pay[j]))
     96             {
     97 
     98                 pay[j] = cost + G[k][j][1];  
     99             }
    100         }
    101 
    102     }
    103 
    104 }

    以上是用邻接矩阵存储的,还有一种方法是使用邻接表来实现,以下是用C++写的,个人感觉更容易理解一些,空间复杂度也小一些

     1 #include<stdio.h>
     2 #include<queue>
     3 #include<vector>
     4 using namespace std;
     5 
     6 struct E
     7 {
     8     int next;
     9     int cost;
    10     int dis;
    11 };
    12 vector<E> edge[501];
    13 bool mark[501];
    14 int dis[501];
    15 int cost[501];
    16 
    17 int main()
    18 {
    19     int n,m,S,T;  //起点终点
    20     int i,j;
    21     E temp;
    22     int newP;
    23     while( scanf("%d%d%d%d",&n,&m,&S,&T)!=EOF)
    24     {
    25         if( n==0 && m==0) break;
    26 
    27         for( i=0; i<=n; i++)
    28         {
    29             edge[i].clear();   //初始化邻接链表
    30             dis[i] = -1;
    31             mark[i] = false;
    32             cost[i] = 0;
    33         }
    34         while( m--)
    35         {
    36             int a,b,d,c;
    37             scanf("%d%d%d%d",&a,&b,&d,&c);
    38             temp.cost = c;
    39             temp.next = b;
    40             temp.dis = d;
    41             edge[a].push_back(temp);
    42             temp.next = a;
    43             edge[b].push_back(temp);  //无向图,故每条边信息都要添加到两个顶点的单链表中
    44         }
    45 
    46         dis[S] = 0;
    47         mark[S] = 1;
    48         newP = S;  //起点为s
    49         for( i=1; i<n; i++)
    50         {
    51             for( j=0; j<edge[newP].size(); j++)
    52             {
    53                 //更新一个顶点对它的边表内结点的距离
    54                 int next = edge[newP][j].next;
    55                 int c = edge[newP][j].cost;
    56                 int d = edge[newP][j].dis;
    57                 if( mark[next]==true) continue;
    58                 if( dis[next]==-1 || dis[next]>dis[newP]+d
    59                         || ((dis[next]==dis[newP]+d) &&(cost[next]>cost[newP]+c)))
    60                 {
    61                     dis[next] = dis[newP]+d;
    62                     cost[next] = cost[newP]+c;
    63                 }
    64             }
    65             int minx = 66666666;
    66             for( j=0; j<=n; j++)
    67             {
    68                 //寻找这个顶点出发的最小值
    69                 if( mark[j]==true) continue;
    70                 if( dis[j]==-1) continue;
    71                 if( dis[j]<minx)
    72                 {
    73                     minx = dis[j];
    74                     newP = j;
    75                 }
    76             }
    77             mark[newP] = true;
    78         }
    79         printf("%d %d
    ",dis[T],cost[T]);
    80     }
    81     return 0;
    82 }
    在这个国度中,必须不停地奔跑,才能使你保持在原地。如果想要寻求突破,就要以两倍现在速度奔跑!
  • 相关阅读:
    逻辑运算(二)
    Rust基础类型
    Rust简单demo
    逻辑基础(一)
    webpack配置typescript项目
    Go并发原理
    JS实现取任意类型的数组交集并集方法的思考
    JS 可逆加密的一种实现
    所有中文复姓
    将中文姓名转为拼音英文名的一种实现
  • 原文地址:https://www.cnblogs.com/yuxiaoba/p/8342538.html
Copyright © 2020-2023  润新知