旅游规划 (25分)Dijkstra算法

Dijkstra算法:用来解决单源最短路问题,就是给出一个图的起点,通过算法可以得到这个点到达其他所有点的最短距离。

接下来简单讲一下Dijkstra算法:
假设现在有6个城市(v0~v5),现在要用Dijkstra算法求出由V0到其他城市的最短路径。
在这里插入图片描述
下面讲一下步骤:(假设现在所有城市都关闭了,城市之间的路都被遮住了,只有开放这个城市之后,该城市到其他城市的路才会开放)(用蓝色代表关闭城市,橙色代表开放城市)
(1)每次都从没有开放的城市中选择距离V0最近的城市,前往开放。
(2)开放Vk之后,开放从他出发的所有道路,并查看,在以Vk为中介点的情况下,能不能让从V0到达某些还没有开放的城市的最短距离变小。如果能,则将那个最短距离覆盖到对应的城市上。

在这里插入图片描述
(每个城市到自己的距离都是0,在城市未开放时到其他城市的距离都为INF(非常大))
1)当前还没有开放的城市是{v0,v1,v2,v3,v4,v5},从v0出发,距离最短的是他自己(v0-V0距离为0,到其他所有城市距离为INF),所以开放V0,这样(V0-V1,V0-V4,V0-V3的路就都开放了)(V0-V1最短距离为1,V0-V3最短距离为4,V0-V4最短距离为4
在这里插入图片描述
2)从{V1,V2,V3,V4,V5}中选最短距离,可以看出是V1,因此开放V1。此时V0-V3的最短距离就从4变成了3(现在V0-V1最短距离为1,V0-V3最短距离为3,V0-V4最短距离为4)
在这里插入图片描述

3)从{V2,V3,V4,V5}中选最短距离,可以看出是V3,开放V3。(现在V0-V1最短距离为1,V0-V2最短距离为5,V0-V3最短距离为3,V0-V4最短距离为4
在这里插入图片描述
4){V2,V4,V5}中选最短路,选V4.(现在V0-V1最短距离为1,V0-V2最短距离为5,V0-V3最短距离为3,V0-V4最短距离为4,V0-V5最短路径为7
在这里插入图片描述
5)开放V2,最后开放V5。因此V0-V5的最短距离变为6.在这里插入图片描述

最后得到的结果就是(V0-V1最短距离为1,V0-V2最短距离为5,V0-V3最短距离为3,V0-V4最短距离为4,V0-V5最短路径为6

下面给一道与该算法有关的题
7-9 旅游规划 (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

题中做成图就是这样,d代表路长度,cost代表收费
在这里插入图片描述
代码实现(C++)

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
const int maxv=505;
const int inf=10000000;
//n为顶点数,m为边数,st为起点 ,ed为终点,G[][]为距离矩阵,cost为花费矩阵 
int n,m,st,ed,G[maxv][maxv],cost[maxv][maxv];

//d记录最短距离,c记录最小花费 
int d[maxv],c[maxv];

bool vis[maxv]={false};//标记数组,vis[i]=true表示已访问

void dijk(int s)//起点s 
{
	fill(d,d+maxv,inf);//fill函数将整个d数组赋为inf
	fill(c,c+maxv,inf);
	 
	d[s]=0;//起点s到自身的距离为0;
	c[s]=0;
	for(int i=0;i<n;i++)
	{
		int u=-1,min=inf;//u使d[u]最小,min存放该最小的d[u];
		for(int j=0;j<n;j++)
		{
			if(vis[j]==false&&d[j]<min)
			{
				u=j;
				min=d[j];
			}
		 } 
		 if(u==-1) return ;//找不到小于inf 的d[u],说明剩下的顶点和起点s不连通
	     vis[u]=true;
	    for(int v=0;v<n;v++)
	    {
	 	    if(vis[v]==false&&G[u][v]!=inf)//如果v未访问&&u能到达v
			 {
			 	if(d[u]+G[u][v]<d[v])
			 	{
			 		d[v]=d[u]+G[u][v];//优化d[v]; 
			 		c[v]=c[u]+cost[u][v];//优化c[v];
					
				 }
				 else if(d[u]+G[u][v]==d[v])//如果路径长度相等 
				 {
				 	if(c[u]+cost[u][v]<c[v])
				 	{
				 		c[v]=c[u]+cost[u][v];
						
					 }
				  } 
			 	
			  } 
	    } 
	 } 
	 
 } 

int main()
{
	
	cin>>n>>m>>st>>ed;
	int u,v;
	fill(G[0],G[0]+maxv*maxv,inf);//初始化图
	for(int i=0;i<m;i++)
	{
		scanf("%d%d",&u,&v);
		scanf("%d%d",&G[u][v],&cost[u][v]);
		G[v][u]=G[u][v];
		cost[v][u]=cost[u][v];
	 } 
	 dijk(st);
	 cout<<d[ed]<<' '<<c[ed];
}
  • 4
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

天金小麻花

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值