7-10 旅游规划 (25 分)
7-10 旅游规划 (25 分)
有了一张自驾旅游路线图,你会知道城市间的高速公路长度、以及该公路要收取的过路费。现在需要你写一个程序,帮助前来咨询的游客找一条出发地和目的地之间的最短路径。如果有若干条路径都是最短的,那么需要输出最便宜的一条路径。
输入格式:
输入说明:输入数据的第1行给出4个正整数N、M、S、D,其中N(2≤N≤500)是城市的个数,顺便假设城市的编号为0~(N−1);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; }
作者:7oDo
仅供参考,请勿抄袭。
Hang Hang Hang !!!