最短路,dijsktra 算法,HDU-2544

从最开始认识算法,到现在被吸引,这种感觉有点其妙。开始我认为算法就是简单的数学问题,到现在我认为算法真的是一种思想,一种逻辑思维让我们的大脑更加的清楚认识到这个问题的答案,从开始到最后的一步步推理,一步步接近正确答案的兴奋,这种兴奋,让我对算法着迷。LOVE 算法。LOVE计算机。

好吧不发牢骚了,让我们一起去深入了解一下如何求最短路径。有了这种思想(算法思想),我觉得真的很神奇。

给你好多好多个岛,然后他们某两个岛之间有路(路何以重复)然后让把你放到其中一个岛上,让你向另一个岛逃亡,

这个问题的本质就是,让你从起点岛到终点岛,找到一个最短的路径。

现在我们来举一个例子,这个是个无向图。

看到这个图了吧,下面他会让你找1岛到任何一个岛的距离最小值。

我们用一个数组来存这个距离

第一次我们先把1岛当作基本的开始对连着1岛的所有岛遍历(更新路径)就是所有和1岛相连的,不相连的距离先假设为无穷大

.然后在这6个距离中找到最小的dis[2]也就是10,标记一下(标记一下下次再次更新的时候不需要更新这个岛,因为这个距离已经是这个岛到1岛的最短路径了),然后更新和2岛相连的岛如果距离小于目前距离则更新(就是我用红色圈起来的),也就是1-2-3的距离从无穷大到60,

之后继续找这个数组里没有被标记过的最小值,30,标记一下更新与4岛相连的岛到1岛的距离,1岛到3岛由1-2-3到1-4-3距离由60变成50,1岛到5岛由1-5变为1-4-5距离由100到90.

然后继续找最小没有被标记过的,50,标记一下,更新一下跟3岛相连距离1岛有没有变近的,发现5岛变近了从90变到了60,路径由1-4-5到1-2-3-5.

继续按这个原则更新直到最后全部点都更新完成。我们就找到了所有岛到1岛的最短路径

,hello,hello,~~~~我讲清楚了没呢,下面让我给大家再来个图试试手

答案就是

我们下来看一个例题

HDU-2544:http://acm.hdu.edu.cn/showproblem.php?pid=2544

题目的意思就是从1到n的距离最短是多少。

上代码

#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
const int INF=0x3f3f3f3f;
const int MAXN=155;
int n,m;
int mp[MAXN][MAXN],dis[MAXN];//mp是为了存邻接矩阵,dis标记到1最短距离
bool vis[MAXN];//标记是否遍历过
void init(){//初始化
	memset(vis,0,sizeof(vis));
	memset(dis,0,sizeof(dis));
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=n;j++){
			if(i==j) mp[i][j]=0;
			else mp[i][j]=INF;
		}
	}
}
void dijkstra(){
	int minn,k=-1;
	for(int i=1;i<=n;i++)
	dis[i]=mp[1][i];
	dis[1]=0;
	vis[1]=1;
	for(int i=1;i<=n;i++)//从1遍历到n
	{
		minn=INF; 
		for(int j=1;j<=n;j++)//每次找到距离1最近且没有被标记的点
		{
			if(dis[j]<minn&&!vis[j])
			{
				minn=dis[j];
				k=j;
			}
		}
		vis[k]=1;//标记一下
		for(int j=1;j<=n;j++)//松弛
            if(!vis[j])//如果没有被标记且距离变小,就松弛一下
            dis[j]=min(dis[j],dis[k]+mp[k][j]);//两个数的最小值
	}
	cout<<dis[n]<< endl;
}
int main(){
	while(scanf("%d%d",&n,&m)&& n+m)
	{
		init();
		int a,b,c;
		for(int i=1;i<=m;i++)//存图
		{
			cin>>a>>b>>c;
			if(mp[a][b]>c){
				mp[a][b]=c;
				mp[b][a]=c;
			}
		}
		dijkstra();
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/Harington/article/details/81974272