零零散散学算法之具体解释几种最短路径

深入解析最短路径算法

正文

第一节 问题的提出及解决方法

所谓最短路径问题,能够说有两种情况来描写叙述。

描写叙述一:在图论中,指的是寻找图中两个节点之间的最短距离。例如以下图

描写叙述二:在现实生活中,指的是找到从一个地方到还有一个地方的近期距离。例如以下图

上述两种情况的本质是一样的,即求一个点到还有一个点的最短路径。好了,问题已经提出来了,那怎么解决呢?解决该问题的方法还是比較多的,只是因为各个路径算法所相应的问题条件不同,我们可依据不同的情况,选择不同的路径算法。

本文将介绍三种最短路径算法,各自是:戴克斯特拉算法(Dijkstra algorithm),弗洛伊德算法(Floyd algorithm)以及A*搜索算法。

第二节 戴克斯特拉算法(Dijkstra algorithm)

该算法解决的是有向图中单个源点到其它顶点的最短路径问题。

戴克斯特拉算法的实现步骤例如以下:

第一步:用带权的矩阵WeiArcs来表示带权有向图,假设图中的两个顶点vi和vj是连通的,则用WeiArcs[i][j]表示这两个顶点所形成边的权值;假设vi和vj不连通,即<vi,vj>这条边不存在,那么将WeiArcs[i][j]置为∞。

第二步:设S为已求得的从某一顶点v始发的最短路径的终点的集合,且S的初始状态为空,初始化时,将始发顶点置于S集合中。那么从v出发到图中其余各个顶点vi可能达到的最短路径长度的初值为D[i]。

第三步:选择一顶点vj,使得vj就是当前求得的一条从顶点v出发的最短路径的终点。此时令S = S ∪ {vj}。

第四步:改动从v出发到集合V-S(V为图顶点的集合)中任一顶点vk可达的最短路径长度。假设D[j]+WeiArcs[j][k] < D[K],则D[k] = D[j] + WeiArcs[j][k]。

第五步:反复操作第三步、第四步共N-1次,由此就能求得从v出发到图中其余各个顶点的最短路径。

好了,实现过程就是这样。只是光有文字描写叙述不行,要更直白的表达这个过程,我觉得用图像表述是一个非常好的选择。例如以下图所看到的

从运算过程表中,我们可知v0到其余个点的最短路径,例如以下图

上述过程描写叙述的戴克斯特拉算法的代码例如以下:

int ShortPath(MGraph G,int v0,PathMatrix &P,ShortPathTable &D)
{
	//用戴克斯特拉算法求有向图G中v0顶点到其余顶点v的最短路径P[v]及带权长度D[v]。
	//若P[v][w]为TRUE,则w是从v0到v当前求得最短路径上的顶点。
	//final[v]为TRUE当且仅当v∈S,即已经求得从v0到v的最短路径。

	for(v = 0;v < G.vexmun;v++)
	{
		final[v] = FALSE;
		D[v] = G.WeiArcs[v0][v];
		for(w = 0;w < G.vexnum;w++)
			P[v][w] = FALSE;	//设空路径
		if(D[v] < INFINITY)
		{
			p[v][v0] = TRUE;
			p[v][v] = TRUE;
		}
	}

	D[v0] = 0;final[v0] = TRUE;	//初始化,v0顶点属于S集合

	//開始主循环,每次求得v0到某个顶点v的最短路径,并将v加到S集合中
	for(i = 1; i < G.vexnum; i++)	//其余G.vexnum - 1个顶点
	{
		min = INFINITY;	//当前所知离v0点的近期距离
		for(w = 0;w < G.vexnum; i++)
		{
			if(!final[w])	//w顶点在V - S中
			{
				if(D[w] < min)	//w顶点离v0更近
				{
					v = w;
					min = D[w];
				}
			}
		}
		final[v] = TRUE;	//离v0顶点近期的v添?到S中

		for(w = 0;w < G.vexnum;w++)	//更新当前最算路径及距离
		{
			if(!final[w] && (min + G.WeiArcs < D[w]))
			{
				D[w] = min + G.WeiArcs[v][w];
				//p[w] = P[v] + P[w];
				P[w] = P[v];
				P[w][w] = TRUE;
			}
		}
	}
	return 0;
}

ok,Dijkstra algorithm介绍完了。

第三节 弗洛伊德算法(Floyd algorithm)

该算法解决的是有向带权图中两顶点之间最短路径的问题。

弗洛伊德算法的设计步骤例如以下:

用带权的矩阵WeiArcs来表示带权有向图,假设图中的两个顶点vi和vj是连通的,则用WeiArcs[i][j]表示这两个顶点所形成边的权值;假设vi和vj不连通,即<vi,vj>这条边不存在,那么将WeiArcs[i][j]置为∞。

要求:求节点vi到节点vj的最短路径。

设D(i,j,k)为从节点vi到节点vj的以vk(vk∈(0,1,...k))节点为中间节点的最短路径的长度。比如:从vi到vj这条路径上经过节点vm和节点vk,那么可表示为:vi-->vm-->vk-->vj。

那么,就有:1.若最短路径经过节点vk,则D(i,j,k) = D(i,k,k-1) + D(k,j,k-1);

2.若最短路径不经过节点vk,则D(i,j,k) = D(i,j,k-1)。

所以,求的vi到vj的最短路径可表示为:

D(i,j,k) = min(D(i,k,k-1) + D(k,j,k-1), D(i,j,k-1))。

老办法,图示的步骤例如以下:

求解的过程见下图:

上述过程描写叙述的弗洛伊德算法的代码例如以下:

int ShortPath(MGraph G,int v0,PathMatrix &P,ShortPathTable &D)
{
	//用Floyd算法求有向图中各对顶点v和w之间的最短路径P[v][w]及其带权长度D[v][w]。
	//若p[v][w][u]为TRUE,则u是从v到w当前求得的最短路径上的顶点
	for(v = 0;v < G.vexnum;v++)
		for(w = 0;w < G.vexnum;w++)
		{
			D[v][w] = G.arcs[v][w];
			if(D[v][w] < INFINITY)	//从v到w有直接路径
			{
				P[v][w][u] = TRUE;
				P[v][w][w] = TRUE;
			}
		}

	for(u = 0;u < G.vexnum;u++)
		for(v = 0;v < G.vexnum;v++)
			for(w = 0;w < G.vexnum;w++)
			{
				if(D[v][u] + D[u][w] < D[v][w])	//从v经u到w的一条更短路径
					D[v][w] = D[v][u] < D[u][w];
				for(i = 0;i < G.vexnum;i++)
					P[v][w][i] = P[v][u][i] || P[u][w][i];
			}
	return 0;
}

第四节 A*搜索算法

A*搜索算法,俗称A星算法。这是一种在图平面上,有多个节点的路径,求出最低通过成本的算法。经常使用于游戏中的NPC的移动计算,或线上游戏的BOT的移动计算上。该算法像Dijkstra算法一样,能够找到一条最短路径;也像BFS一样,进行启示式的搜索。

A*算法最核心的部分,就在于它的一个估值函数的设计上:f(n)=g(n)+h(n)。当中,g(n)表示从起始点到任一点n的实际距离,h(n)表示随意顶点n到目标顶点的估算距离,f(n)是每一个可能试探点的估值。这个估值函数遵循下面特性:

?假设h(n)为0,仅仅需求出g(n),即求出起点到随意顶点n的最短路径,则转化为单源最短路径问题,即Dijkstra算法;

?假设h(n)<=“n到目标的实际距离”,则一定能够求出最优解。并且h(n)越小,须要计算的节点越多,算法效率越低。

我们能够这样来描写叙述:从出发点(StartPoint,缩写成sp)到终点(EndPoint,缩写成ep)的最短距离是一定的,于是我们能够写一个估值函数来预计出发点到终点的最短距离。假设程序尝试着从出发点沿着某条线路移动到了路径上的还有一个点(Otherpoint,缩写成op),那么我们觉得这个方法所得到的从sp到ep间的预计距离为:从sp到op实际已走的距离加上预计函数估出的从op到ep的距离。如此,不管我们的程序搜索展开到哪一步,都会得到一个预计值,每一次决策后,将评估值和等待处理的方案一起排序,然后挑出待处理的各个方案中最有可能是最短路线的一部分的方案展开到下一步,
一直循环直到对象移动到目的地,或全部方案都尝试过,却没有找到一条通向目的地的路径则结束。

A*搜索算法的图解过程请看:http://blog.vckbase.com/panic/archive/2005/03/20/3778.html

第五节 相关说明

參考资料:数据结构(严蔚敏)、维基百科之A*搜索算法

第六节 结束语

想想,写写,画画......

时间: 2024-10-05 14:59:25

零零散散学算法之具体解释几种最短路径的相关文章

PHP-密码学算法及其应用-散列函数

转自http://www.smatrix.org/bbs/simple/index.php?t5591.html //////////////////////////////////////////////////////////////////////////////目录1.    PHP的散列函数及其应用2.    PHP中的对称密码算法及其应用3.    PHP的公钥密码算法及其应用//////////////////////////////////////////////////////

1180: 零起点学算法87——超级楼梯(有疑问)

1180: 零起点学算法87--超级楼梯 Time Limit: 1 Sec  Memory Limit: 128 MB   64bit IO Format: %lldSubmitted: 1803  Accepted: 431[Submit][Status][Web Board] Description 有一楼梯共M级,刚开始时你在第一级,若每次只能跨上一级或二级,要走上第M级,共有多少种走法? Input 输入数据首先包含一个整数N,表示测试实例的个数,然后是N行数据,每行包含一个整数M(1

1135: 零起点学算法42——多组测试数据(求和)IV

1135: 零起点学算法42--多组测试数据(求和)IV Time Limit: 1 Sec  Memory Limit: 64 MB   64bit IO Format: %lldSubmitted: 2439  Accepted: 1277[Submit][Status][Web Board] Description 还有一些输入是以上几种情况的组合,具体根据题目对前面几种情况进行组合 比如题目要求是多组测试数据 每组测试数据首先输入一个整数n(如果n=0就表示结束) 然后再输入n个整数 这

PHP-密码学算法及其应用-对称密码算法

转自:http://www.smatrix.org/bbs/simple/index.php?t5662.html //////////////////////////////////////////////////////////////////////////////目录1.    PHP的散列函数及其应用2.    PHP中的对称密码算法及其应用3.    PHP的公钥密码算法及其应用/////////////////////////////////////////////////////

0基础学算法 第二弹 排序

大家好啊,这是0算法基础学算法系列第二篇,上次我在第一弹里讲了关于流程图的内容,我寻思着,这次讲些什么好呢,于是我决定,教大家一个很基础的算法,那就是排序,排序有很多方法,如果你有更多方法请在评论区里留言哦. 排序在程序中特别实用,常用的有快速排序,桶排序,冒泡排序,插入排序等等,在这里我不建议使用冒泡排序或者插入排序,建议桶排序和快速排序,这两个排序非常实用,时间复杂度低,理解起来也很容易,首先,你先思考一下,怎么用程序进行排序,然后你再来看看你的思路合理不合理,最后试着用程序实现它,实现后你

1169: 零起点学算法76——绝对公正的裁判

1169: 零起点学算法76--绝对公正的裁判 Time Limit: 1 Sec  Memory Limit: 128 MB   64bit IO Format: %lldSubmitted: 510  Accepted: 336[Submit][Status][Web Board] Description 大家知道我们学校的OnlineJudge吗?,你知道他会告诉你什么呢? Compiling : 您提交的代码正在被编译.Running : 您的程序正在OJ上运行.Judging : OJ

1165: 零起点学算法72——首字母变大写

1165: 零起点学算法72--首字母变大写 Time Limit: 1 Sec  Memory Limit: 64 MB   64bit IO Format: %lldSubmitted: 705  Accepted: 439[Submit][Status][Web Board] Description 输入一个英文句子,将每个单词的第一个字母改成大写字母. Input 输入数据包含多个测试实例,每个测试实例是一个长度不超过100的英文句子,占一行. Output 请输出按照要求改写后的英文句

1127: 零起点学算法34——继续求多项式

1127: 零起点学算法34--继续求多项式 Time Limit: 1 Sec  Memory Limit: 64 MB   64bit IO Format: %lldSubmitted: 3481  Accepted: 1985[Submit][Status][Web Board] Description 输入1个正整数n, 计算1+(1+2)+(1+2+3)+...+(1+2+3+...+n) Input 输入正整数n(多组数据) Output 输出1+(1+2)+(1+2+3)+...+

1128: 零起点学算法35——再求多项式(含浮点)

1128: 零起点学算法35--再求多项式(含浮点) Time Limit: 1 Sec  Memory Limit: 64 MB   64bit IO Format: %lldSubmitted: 2141  Accepted: 1002[Submit][Status][Web Board] Description 输入一个整数n,计算 1+1/(1-3)+1/(1-3+5)+...+1/(1-3+5-...+2n-1)的值 Input 输入一个整数n(多组数据) Output 出1+1/(1