




版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、TOC o 1-5 h z HYPERLINK l bookmark0算法的思想2 HYPERLINK l bookmark2算法的描述2 HYPERLINK l bookmark4算法的举例2A*算法 HYPERLINK l bookmark16原理简介2 HYPERLINK l bookmark26详细内容2 HYPERLINK l bookmark110A*算法误区17 HYPERLINK l bookmark112A*算法总结SummaryoftheA*Method)17 HYPERLINK l bookmark118FLOYD算法17 HYPERLINK l bookmark120定
2、义17核心思路1.8算法过程1.8优缺点分析1.8JOHNSON算法过程1.8优缺点分析1.8JOHNSON算法23TOC o 1-5 h z HYPERLINK l bookmark172Johnson算法要求23 HYPERLINK l bookmark174Johnson算法结构要求23 HYPERLINK l bookmark176Johnson算法数据结构23 HYPERLINK l bookmark180Johnson算法的内容23 HYPERLINK l bookmark182Johnson算法源程序23 HYPERLINK l bookmark8DIJKSTRA算法27 HYP
3、ERLINK l bookmark184算法简介2.7. HYPERLINK l bookmark12算法描述2.7. HYPERLINK l bookmark188复杂度分析2.7.算法实现2.8测试样例3.0算法应用的实例算法的思想设图中有n个结点,设置一个集会u存放已经求出最短路径的结点(初始时u中的元素是源点),v-u是尚未确定最短路径的顶点的集合。每次从v-u集合中找这样一个结点best:best是u集合中结点的邻接点,到源点的距离最短(等于到父结点的距离加上父结点到源点的距离)。然后把该best_j置入u集合中,直到u=v。算法的描述最短路经计算分静态最短路计算和动态最短路计算。静
4、态路径最短路径算法是外界环境不变,计算最短路径。主要有Dijkstra算法,A*算法。动态路径最短路是外界环境不断发生变化,即不能计算预测的情况下计算最短路。典型的有D*算法。算法的举例A*算法原理简介A*(A-Star)算法是一种静态路网中求解最短路最有效的方法。公式表示为:f(n)=g(n)+h(n),其中f(n)是节点n从初始点到目标点的估价函数,g(n)是在状态空间中从初始节点到n节点的实际代价,h(n)是从n到目标节点最佳路径的估计代价。保证找到最短路径(最优解的)条件,关键在于估价函数h(n)的选取:估价值h(n)=n到目标节点的距离实际值,这种情况下,搜索的点数多,搜索范围大,效
5、率低。但能得到最优解。如果估价值实际值,搜索的点数少,搜索范围小,效率高,但不能保证得到最优解。估价值与实际值越接近,估价函数取得就越好。例如对于几何路网来说,可以取两节点间欧几理德距离(直线距离)做为估价值,即f=g(n)+sqrt(dx-nx)*(dx-nx)+(dy-ny)*(dy-ny);这样估价函数f在g值一定的情况下,会或多或少的受估价值h的制约,节点距目标点近,h值小,f值相对就小,能保证最短路的搜索向终点的方向进行。明显优于Dijstra算法的毫无无方向的向四周搜索。conditionsofheuristicOptimistic(mustbelessthanorequaltot
6、herealcost)Asclosetotherealcostaspossible详细内容初始A*算法主要搜索过程:创建两个表,OPEN表保存所有已生成而未考察的节点,CLOSED表中记录已访问过的节点。遍历当前节点的各个节点,将n节点放入CLOSE中,取n节点的子节点X,-算X的估价值-While(OPEN!=NULL)从OPEN表中取估价值f最小的节点n;if(n节点=目标节点)break;elseif(XinOPEN)比较两个X的估价值f注意是同一个节点的两个不同路径的估价值if(X的估价值小于OPEN表的估价值)更新OPEN表中的估价值;/取最小路径的估价值if(XinCLOSE)比较
7、两个X的估价值注意是同一个节点的两个不同路径的估价值if(X的估价值小于CLOSE表的估价值)更新CLOSE表中的估价值;把X节点放入OPEN/取最小路径的估价值if(Xnotinboth)求X的估价值;并将X插入OPEN表中;还没有排序将n节点插入CLOSE表中;按照估价值将OPEN表中的节点排序;实际上是比较OPEN表内节点f的大小,从最小路径的节点向下进行。启发式搜索其实有很多的算法,比如:局部择优搜索法、最好优先搜索法等等。当然A*也是。这些算法都使用了启发函数,但在具体的选取最佳搜索节点时的策略不同。象局部择优搜索法,就是在搜索的过程中选取“最佳节点”后舍弃其他的兄弟节点,父亲节点,
8、而一直得搜索下去。这种搜索的结果很明显,由于舍弃了其他的节点,可能也把最好的节点都舍弃了,因为求解的最佳节点只是在该阶段的最佳并不一定是全局的最佳。最好优先就聪明多了,他在搜索时,便没有舍弃节点(除非该节点是死节点),在每一步的估价中都把当前的节点和以前的节点的估价值比较得到一个“最佳的节点”。这样可以有效的防止“最佳节点”的丢失。那么A*算法又是一种什么样的算法呢?其实A*算法也是一种最好优先的算法。只不过要加上一些约束条件罢了。由于在一些问题求解时,我们希望能够求解出状态空间搜索的最短路径,也就是用最快的方法求解问题,A*就是干这种事情的!我们先下个定义,如果一个估价函数可以找出最短的路径
9、,我们称之为可采纳性。A*算法是一个可采纳的最好优先算法。A*算法的估价函数可表示为:f(n)=g(n)+h(n)这里,f(n)是估价函数,g(n)是起点到终点的最短路径值,h(n)是n到目标的最断路经的启发值。由于这个f(n)其实是无法预先知道的,所以我们用前面的估价函数f(n)做近似。g(n)代替g(n),但g(n)=g(n)才可(大多数情况下都是满足的,可以不用考虑),h(n)代替h(n),但h(n)v=h(n)才可(这一点特别的重要)。可以证明应用这样的估价函数是可以找到最短路径的,也就是可采纳的。我们说应用这种估价函数的最好优先算法就是A*算法。举一个例子,其实广度优先算法就是A*算
10、法的特例。其中g(n)是节点所在的层数,h(n)=0,这种h(n)肯定小于h(n),所以由前述可知广度优先算法是一种可采纳的。当然它是一种最臭的A*算法。再说一个问题,就是有关h(n)启发函数的信息性。h(n)的信息性通俗点说其实就是在估计一个节点的值时的约束条件,如果信息越多或约束条件越多则排除的节点就越多,估价函数越好或说这个算法越好。这就是为什么广度优先算法的那么臭的原因了,谁叫它的h(n)=0,一点启发信息都没有。但在游戏开发中由于实时性的问题,h(n)的信息越多,它的计算量就越大,耗费的时间就越多。就应该适当的减小h(n)的信息,即减小约束条件。但算法的准确性就差了,这里就有一个平衡
11、的问题。概述虽然掌握了A*算法的人认为它容易,但是对于初学者来说,A*算法还是很复杂的。搜索区域(TheSearchArea)我们假设某人要从A点移动到B点,但是这两点之间被一堵墙隔开。如图1,绿色是A,红色是B,中间蓝色是墙。图1你应该注意到了,我们把要搜寻的区域划分成了正方形的格子。这是寻路的第一步,简化搜索区域,就像我们这里做的一样。这个特殊的方法把我们的搜索区域简化为了2维数组。数组的每一项代表一个格子,它的状态就是可走(walkalbe)和不可走(unwalkable)。通过计算出从A到B需要走过哪些方格,就找到了路径。一旦路径找到了,人物便从一个方格的中心移动到另一个方格的中心,直
12、至到达目的地。方格的中心点我们成为“节点(nodes)”。如果你读过其他关于A*寻路算法的文章,你会发现人们常常都在讨论节点。为什么不直接描述为方格呢?因为我们有可能把搜索区域划为为其他多变形而不是正方形,例如可以是六边形,矩形,甚至可以是任意多变形。而节点可以放在任意多边形里面,可以放在多变形的中心,也可以放在多边形的边上。我们使用这个系统,因为它最简单。开始搜索(StartingtheSearch)一旦我们把搜寻区域简化为一组可以量化的节点后,就像上面做的一样,我们下一步要做的便是查找最短路径。在A*中,我们从起点开始,检查其相邻的方格,然后向四周扩展,直至找到目标。我们这样开始我们的寻路
13、旅途:从起点A开始,并把它就加入到一个由方格组成的openlist(开放列表)中。这个openlist有点像是一个购物单。当然现在openlist里只有一项,它就是起点A,后面会慢慢加入更多的项。Openlist里的格子是路径可能会是沿途经过的,也有可能不经过。基本上openlist是一个待检查的方格列表。查看与起点A相邻的方格(忽略其中墙壁所占领的方格,河流所占领的方格及其他非法地形占领的方格),把其中可走的(walkable)或可到达的(reachable)方格也加入到openlist中。把起点A设置为这些方格的父亲(parentnode或parentsquare)。当我们在追踪路径时,这
14、些父节点的内容是很重要的。稍后解释。3.把A从openlist中移除,加入到closelist(封闭列表)中,closelist中的每个方格都是现在不需要再关注的。如下图所示,深绿色的方格为起点,它的外框是亮蓝色,表示该方格被加入到了closelist。与它相邻的黑色方格是需要被检查的,他们的外框是亮绿色。每个黑方格都有一个灰色的指针指向他们的父节点,这里是起点A。图2下一步,我们需要从openlist中选一个与起点A相邻的方格,按下面描述的一样或多或少的重复前面的步骤。但是到底选择哪个方格好呢?具有最小F值的那个。路径排序(PathSorting)计算出组成路径的方格的关键是下面这个等式:F
15、=G+H这里,G=从起点A移动到指定方格的移动代价,沿着到达该方格而生成的路径。H=从指定的方格移动到终点B的估算成本。这个通常被称为试探法,有点让人混淆。为什么这么叫呢,因为这是个猜测。直到我们找到了路径我们才会知道真正的距离,因为途中有各种各样的东西(比如墙壁,水等)。我们的路径是这么产生的:反复遍历openlist,选择F值最小的方格。这个过程稍后详细描述。我们还是先看看怎么去计算上面的等式。如上所述,G是从起点A移动到指定方格的移动代价。在本例中,横向和纵向的移动代价为10,对角线的移动代价为14。之所以使用这些数据,是因为实际的对角移动距离是2的平方根,或者是近似的1.414倍的横向
16、或纵向移动代价。使是有10和14就是为了简单起见。比例是对的,我们避免了开放和小数的计算。这并不是我们没有这个能力或是不喜欢数学。使用这些数字也可以使计算机更快。稍后你便会发现,如果不使用这些技巧,寻路算法将很慢。既然我们是沿着到达指定方格的路径来计算G值,那么计算出该方格的G值的方法就是找出其父亲的G值,然后按父亲是直线方向还是斜线方向加上10或14。随着我们离开起点而得到更多的方格,这个方法会变得更加明朗。有很多方法可以估算H值。这里我们使用Manhattan方法,计算从当前方格横向或纵向移动到达目标所经过的方格数,忽略对角移动,然后把总数乘以10。之所以叫做Manhattan方法,是因为
17、这很像统计从一个地点到另一个地点所穿过的街区数,而你不能斜向穿过街区。重要的是,计算H是,要忽略路径中的障碍物。这是对剩余距离的估算值,而不是实际值,因此才称为试探法。把G和H相加便得到F。我们第一步的结果如下图所示。每个方格都标上了F,G,H的值,就像起点右边的方格那样,左上角是F,左下角是G,右下角是H。图3现在让我们看看其中的一些方格。在标有字母的方格,G=10。这是因为水平方向从起点到那里只有一个方格的距离。与起点直接相邻的上方,下方,左方的方格的G值都是10,对角线的方格G值都是14。H值通过估算起点于终点(红色方格)的Manhattan距离得到,仅作横向和纵向移动,并且忽略沿途的墙
18、壁。使用这种方式,起点右边的方格到终点有3个方格的距离,因此H=30。这个方格上方的方格到终点有4个方格的距离(注意只计算横向和纵向距离),因此H=40。对于其他的方格,可以用同样的方法知道H值是如何得来的。每个方格的F值,再说一次,直接把G值和H值相加就可以了。继续搜索(ContinuingtheSearch)为了继续搜索,我们从openlist中选择F值最小的(方格)节点,然后对所选择的方格作如下操作:把它从openlist里取出,放到closelist中。检查所有与它相邻的方格,忽略其中在closelist中或是不可走(unwalkable)的方格(比如墙,水,或是其他非法地形),如果方
19、格不在openlsit中,则把它们加入到openlist中。把我们选定的方格设置为这些新加入的方格的父亲。如果某个相邻的方格已经在openlist中,则检查这条路径是否更优,也就是说经由当前方格(我们选中的方格)到达那个方格是否具有更小的G值。如果没有,不做任何操作。相反,如果G值更小,则把那个方格的父亲设为当前方格(我们选中的方格),然后重新计算那个方格的F值和G值。如果你还是很混淆,请参考下图。图图4,起点被放入了closelist中。在这些方格中,起点右边的格子的F值40最小,因此我们选择这个方格作为下一个要处理的方格。它的外框用蓝线打亮。首先,我们把它从openlist移到closel
20、ist中(这就是为什么用蓝线打亮的原因了)。然后我们检查与它相邻的方格。它右边的方格是墙壁,我们忽略。它左边的方格是起点,在closelist中,我们也忽略。其他4个相邻的方格均在openlist中,我们需要检查经由这个方格到达那里的路径是否更好,使用G值来判定。让我们看看上面的方格。它现在的G值为14。如果我们经由当前方格到达那里,G值将会为20(其中10为到达当前方格的G值,此外还要加上从当前方格纵向移动到上面方格的G值10)。显然20比14大,因此这不是最优的路径。如果你看图你就会明白。直接从起点沿对角线移动到那个方格比先横向移动再纵向移动要好。当把4个已经在openlist中的相邻方格
21、都检查后,没有发现经由当前方格的更好路径,因此我们不做任何改变。现在我们已经检查了当前方格的所有相邻的方格,并也对他们作了处理,是时候选择下一个待处理的方格了。因此再次遍历我们的openlist,现在它只有7个方格了,我们需要选择F值最小的那个。有趣的是,这次有两个方格的F值都54,选哪个呢?没什么关系。从速度上考虑,选择最后加入openlist的方格更快。这导致了在寻路过程中,当靠近目标时,优先使用新找到的方格的偏好。但是这并不重要。(对相同数据的不同对待,导致两中版本的A*找到等长的不同路径)。我们选择起点右下方的方格,如下图所示。图5当我们检查相邻的方格时,我们发现它右边的方格是墙,忽略
22、之。上面的也一样。我们把墙下面的一格也忽略掉。为什么?因为如果不穿越墙角的话,你不能直接从当前方格移动到那个方格。你需要先往下走,然后再移动到那个方格,这样来绕过墙角。(注意:穿越墙角的规则是可选的,依赖于你的节点是怎么放置的)这样还剩下5个相邻的方格。当前方格下面的2个方格还没有加入openlist,所以把它们加入,同时把当前方格设为他们的父亲。在剩下的3个方格中,有2个已经在closelist中(一个是起点,一个是当前方格上面的方格,外框被加亮的),我们忽略它们。最后一个方格,也就是当前方格左边的方格,我们检查经由当前方格到达那里是否具有更小的G值。没有。因此我们准备从openlist中选
23、择下一个待处理的方格。不断重复这个过程,直到把终点也加入到了openlist中,此时如下图所示。TT5DanY5H5EDHDBE3HEZBEDZBEIQBTS.3QIQB3aFD395D5ainaaa述9aaTT5DanY5H5EDHDBE3HEZBEDZBEIQBTS.3QIQB3aFD395D5ainaaa述9aazaEDea图6注意:在起点下面2格的方格的父亲已经与前面不同了。之前它的G值是28并且指向它右上方的方格。现在它的G值为20,并且指向它正上方的方格。这在寻路过程中的某处发生,使用新路径时G值经过检查并且变得更低,因此父节点被重新设置,G和F值被重新计算。尽管这一变化在本例中并
24、不重要,但是在很多场合中,这种变化会导致寻路结果的巨大变化。那么我们怎么样去确定实际路径呢?很简单,从终点开始,按着箭头向父节点移动,这样你就被带回到了起点,这就是你的路径。如下图所示。从起点A移动到终点B就是简单从路径上的一个方格的中心移动到另一个方格的中心,直至目标图7。就是这么简单图7代码如下:namespaceAStarclassPointpublicPoint()publicPoint(intx,inty)this.x=x;this.y=y;privateintx;publicintXgetreturnx;setx=value;privateinty;publicintYgetret
25、urny;sety=value;classPathprivateinth;publicintHgetreturnh;seth=value;privateintf;publicintFgetreturnf;setf=value;privateintg;publicintGgetreturng;setg=value;privatePointstartPoint;publicPointStartPointgetreturnstartPoint;setstartPoint=value;privatePointendPoint;publicPointEndPointgetreturnendPoint;s
26、etendPoint=value;namespaceAStarclassProgramprivatestaticArrayListcloselist=newArrayList();privatestaticArrayListopenlist=newArrayList();privatestaticPointp_start=newPoint(0,0);privatestaticPointp_end=newPoint(9,9);privatestaticintgw=10,gwh=14;/gh=10,privatestaticintw=10,h=10;/privatestaticstringn_pa
27、th=privatestaticPaths_path=newPath();privatestaticintnum;staticvoidMain(stringargs)inth=(Math.Abs(p_end.X-p_start.Y)+Math.Abs(p_end.Y-p_start.Y)*gw;s_path.F=h;s_path.G=0;s_path.H=h;s_path.StartPoint=p_start;s_path.EndPoint=p_start;doGetF(setDirection(s_path.StartPoint);Sort(openlist);s_path=(Path)op
28、enlistopenlist.Count-1;closelist.Add(s_path);openlist.RemoveAt(openlist.Count-1);if(openlist.Count=0)Console.WriteLine(找不到路径);return;if(s_path.StartPoint.X=p_end.X)&(s_path.StartPoint.Y=p_end.Y)getPath();break;while(true);staticArrayListsetDirection(PointstartPoint)ArrayListdirection=newArrayList();
29、PointnorthEast=newPoint();northEast.X=startPoint.X+1;northEast.Y=startPoint.Y-1;direction.Add(northEast);/东北Pointeast=newPoint();east.X=startPoint.X+1;east.Y=startPoint.Y;direction.Add(east);/东PointsouthEast=newPoint();southEast.X=startPoint.X+1;southEast.Y=startPoint.Y+1;direction.Add(southEast);/东
30、南Pointsouth=newPoint();south.X=startPoint.X;south.Y=startPoint.Y+1;direction.Add(south);/南PointsouthWest=newPoint();southWest.X=startPoint.X-1;southWest.Y=startPoint.Y+1;direction.Add(southWest);/西南Pointwest=newPoint();west.X=startPoint.X-1;west.Y=startPoint.Y;direction.Add(west);/西PointnorthWast=ne
31、wPoint();northWast.X=startPoint.X-1;northWast.Y=startPoint.Y-1;direction.Add(northWast);/西北Pointnorth=newPoint();north.X=startPoint.X;north.Y=startPoint.Y-1;direction.Add(north);/西北returndirection;staticvoidGetF(ArrayListarr)intt=newint2;intG,H,F;for(inti=0;iarr.Count;i+)t0=(Point)arri).X;t1=(Point)
32、arri).Y;if(IsOutScreen(Point)arri)|IsPass(Point)arri)|IsClose(Point)arri)|IsStart(Point)arri)|!IsInTurn(Point)arri)continue;if(t0-s_path.StartPoint.X)*(t1-s_path.StartPoint.Y)!=0)G=s_path.G+gwh;elseG=s_path.G+gw;if(InOpen(Point)arri)if(Gp_start.X)if(arr.Yp_start.Y)if(IsPass(newPoint(arr.X-1,arr.Y)|I
33、sPass(newPoint(arr.X,arr.Y-1)returnfalse;elseif(arr.Yp_start.Y)if(IsPass(newPoint(arr.X-1,arr.Y)|IsPass(newPoint(arr.X,arr.Y+1)returnfalse;elseif(arr.Xp_start.Y)if(IsPass(newPoint(arr.X+1,arr.Y)|IsPass(newPoint(arr.X,arr.Y-1)returnfalse;elseif(arr.Yp_start.Y)if(IsPass(newPoint(arr.X+1,arr.Y)|IsPass(
34、newPoint(arr.X,arr.Y+1)returnfalse;returntrue;staticboolIsOutScreen(Pointarr)if(arr.X0|arr.Y(w-1)|arr.Y(h-1)returntrue;returnfalse;staticboolInOpen(Pointarr)boolresult=false;for(inti=0;iopenlist.Count;i+)if(arr.X=(Path)openlisti).StartPoint.X&arr.Y=(Path)openlisti).StartPoint.Y)result=true;num=i;bre
35、ak;returnresult;staticboolIsClose(Pointarr)boolresult=false;for(inti=0;i1)returntrue;returnfalse;staticvoidSort(ArrayListarr)Pathtemp;for(inti=0;iarr.Count;i+)if(arr.Count=1)break;if(Path)arri).F=(Path)arri+1).F)temp=(Path)arri;arri=arri+1;arri+1=temp;if(i+1)=(arr.Count-1)break;staticvoidgetPath()st
36、ringstr=;Pointt=(Path)closelistcloselist.Count-1).EndPoint;while(true)str+=(+t.X+,+t.Y+);for(inti=0;ig=0;Node-h=(dx-sx)*(dx-sx)+(dy-sy)*(dy-sy);Node-f=Node-g+Node-h;Node-NodeNum=TileNum(dx,dy);Node-x=dx;Node-y=dy;OPEN-NextNode=Node;for(;)BestNode=ReturnBestNode();if(BestNode-NodeNum=TileNumDest)Gene
37、rateSuccessors(BestNode,sx,sy);PATH=BestNode;生成子节点函数:voidAstarPathfinder:GenerateSuccessors(NODE*BestNode,intdx,intdy)intx,y;if(FreeTile(x=BestNode-x-TILESIZE,y=BestNode-y-TILESIZE)GenerateSucc(BestNode,x,y,dx,dy);if(FreeTile(x=BestNode-x,y=BestNode-y-TILESIZE)GenerateSucc(BestNode,x,y,dx,dy);if(Fre
38、eTile(x=BestNode-x+TILESIZE,y=BestNode-y-TILESIZE)GenerateSucc(BestNode,x,y,dx,dy);if(FreeTile(x=BestNode-x+TILESIZE,y=BestNode-y)GenerateSucc(BestNode,x,y,dx,dy);if(FreeTile(x=BestNode-x+TILESIZE,y=BestNode-y+TILESIZE)GenerateSucc(BestNode,x,y,dx,dy);if(FreeTile(x=BestNode-x,y=BestNode-y+TILESIZE)G
39、enerateSucc(BestNode,x,y,dx,dy);if(FreeTile(x=BestNode-x-TILESIZE,y=BestNode-y+TILESIZE)GenerateSucc(BestNode,x,y,dx,dy);if(FreeTile(x=BestNode-x-TILESIZE,y=BestNode-y)GenerateSucc(BestNode,x,y,dx,dy);voidAstarPathfinder:GenerateSucc(NODE*BestNode,intx,inty,intdx,intdy)intg,TileNumS,c=0;NODE*Old,*Su
40、ccessor;g=BestNode-g+1;TileNumS=TileNum(x,y);if(Old=CheckOPEN(TileNumS)!=NULL)for(c=0;cChildc=NULL)break;BestNode-Childc=Old;if(gg)Old-Parent=BestNode;Old-g=g;Old-f=g+Old-h;elseif(Old=CheckCLOSED(TileNumS)!=NULL)for(c=0;cChildc=NULL)break;BestNode-Childc=Old;if(gg)Old-Parent=BestNode;Old-g=g;Old-f=g
41、+Old-h;PropagateDown(Old);ElseSuccessor=(NODE*)calloc(1,sizeof(NODE);Successor-Parent=BestNode;Successor-g=g;Successor-h=(x-dx)*(x-dx)+(y-dy)*(y-dy);Successor-f=g+Successor-h;Successor-x=x;Successor-y=y;Successor-NodeNum=TileNumS;Insert(Successor);for(c=0;cChildc=NULL)break;BestNode-Childc=Successor
42、;A*算法误区A*是一个启发式搜索算法。就是说在一个可以被穷举的有限解空间集中,用比较有效的方法(主要是利用估价函数)求出最优解的算法。A*跟寻路算法没有太多关系,我们只是借助了这个方法来解决寻路这个问题,正如四则运算对于数学题一样,它只是一个基本工具。寻路算法本身有很多种,我们找到算法后,借助A*这个工具实现这个算法而已。A*算法理论上可以得到最优解,不过我们可以通过选择一个更好的估价函数,或是减少解空间来提高性能。A*是传统意义上的地图寻路,其实依据的是这样一种算法:把地图分成若干个格子,反复迭代下去把地图分格子,给格子间的路径一个权值(前面的例子中,格子间的距离都是相等的,我们也可以根据
43、地形划分成不等的距离,即权值,或者定义单向道路,这都是可以的),这是解决寻路问题的关键,但都不是A*算法的范畴。这种一步步尝试的过程,就是一种搜索过程。如果加上启发函数,不让它盲目的寻找,就衍生出很多启发式搜索算法。A*是其中的一种。之所以加一个*号,是因为它的启发式函数是有限制的,这个限制确保它能找到绝对最优解,去掉这个限制,就是A算法了。如果你想出某种算法,比如把地图划分成不规则的区域,或者把地图矢量化。依然可以再此基础上用A*算法这个工具来从中求到最优解。如果想别的方法来寻路,比如拟人的判断,预设路点等等,甚至按走迷宫的方法一样,分叉右转,碰壁回头,那些可以算是对分格寻路方法的一些改进,
44、却都不关A*什么事情。A*算法总结(SummaryoftheA*Method)把起点加入openlist。重复如下过程:遍历openlist,查找F值最小的节点,把它作为当前要处理的节点。把这个节点移到closelist。对当前方格的8个相邻方格的每一个方格?如果它是不可抵达的或者它在closelist中,忽略它。否则,做如下操作。如果它不在openlist中,把它加入openlist,并且把当前方格设置为它的父亲,记录该方格的F,G和H值。如果它已经在openlist中,检查这条路径(即经由当前方格到达它那里)是否更好,用G值作参考。更小的G值表示这是更好的路径。如果是这样,把它的父亲设置为
45、当前方格,并重新计算它的G和F值。如果你的openlist是按F值排序的话,改变后你可能需要重新排序。停止,当你把终点加入到了openlist中,此时路径已经找到了,或者查找终点失败,并且openlist是空的,此时没有路径。保存路径。从终点开始,每个方格沿着父节点移动直至起点,这就是你的路径。Floyd算法定义Floyd算法又称为弗洛伊德算法,插点法,是一种用于寻找给定的加权图中顶点间最短路径的算法。核心思路通过一个图的权值矩阵求出它的每两点间的最短路径矩阵。从图的带权邻接矩阵A=a(i,j)nxn开始,递归地进行n次更新,即由矩阵D(0)=A,按一个公式,构造出矩阵D(1);又用同样地公式
46、由D(1)构造出D(2);弗弗;最后又用同样的公式由D(n-1)构造出矩阵D(n)。矩阵D(n)的i行j列元素便是i号顶点到j号顶点的最短路径长度,称D(n)为图的距离矩阵,同时还可引入一个后继节点矩阵path来记录两点间的最短路径。采用的是松弛技术,对在i和j之间的所有其他点进行一次松弛。所以时间复杂度为0(n人3);其状态转移方程如下:mapi,j:=minmapi,k+mapk,j,mapi,jmapi,j表示i至叮的最短距离K是穷举的断点mapn,n初值应该为0,或者按照题目意思来做。当然,如果这条路没有通的话,还必须特殊处理,比如没有mapi,k这条路算法过程把图用邻接矩阵G表示出来
47、,如果从Vi到Vj有路可达,则Gi,j=dd表示该路的长度;否则Gi,j=空值。定义一个矩阵D用来记录所插入点的信息,Di,j表示从Vi到Vj需要经过的点,初始化Di,j=j。把各个顶点插入图中,比较插点后的距离与原来的距离,Gi,j=min(Gi,j,Gi,k+Gk,j),如果Gi,j的值变小,则Di,j=k。在G中包含有两点之间最短道路的信息,而在D中则包含了最短通路径的信息。比如,要寻找从V5到V1的路径。根据D,假如D(5,1)=3则说明从V5到V1经过V3,路径为V5,V3,V1,如果D(5,3)=3,说明V5与V3直接相连,如果D(3,1)=1,说明V3与V1直接相连。优缺点分析F
48、loyd算法适用于APSP(AIIPairsShortestPaths),是一种动态规划算法,稠密图效果最佳,边权可正可负。此算法简单有效,由于三重循环结构紧凑,对于稠密图,效率要高于执行|V|次Dijkstra算法。优点:容易理解,可以算出任意两个节点之间的最短距离,代码编写简单;缺点:时间复杂度比较高,不适合计算大量数据。如何用floyd算法求出最短路径一:flody是如何实现搜索最短路径的:Floyd又称插点法,它的基本过程如下:首先用图邻接矩阵G表示出来,如果从Vi到Vj有路可达。则G(l,j)=d,d表示该路长度,否则G(l,j)=inf最后图可以用如下图表示:G=023fnffnf
49、9104tiT斗Inf10Inf10In;10r.r90Tr.fInf7nf210419g+Inf0为了搜索出最短路径我们还需要一个矩阵用来记录所插入点的信这个矩阵的D,D(ij)表示从V(i)到V(j)需要经过的点,初始化D(Ij)=jD=I235I235然后把各个顶点插入图中,比较插点后的距离与原来的距离,G(I,j)=min(G(Ij)+G(I,k)+G(kj),如果G(I,j)的值变小,则G(I,j)=k,如在上个图中把Vi的值插入后所得结果为G=023Inf【M4I04Inf(PTn110Inf10|101090nr匝7【叩2100A1a4Tnf0D=12j-456123-4s124
50、5a1Z斗5Zl1n丁41i14s6这样我们把各个值都加入后得到G为G=D=二:如何搜索出最短路径:在G中包含有最短道路的消息,而在D中则包含有最短通路径的信息,如果我从V5到VI的路径则根据D,D(5,1)=3则说名点经过V3,道路为(V5,V3,V1),D(5,3)=3,说明V5与V3直接连接,D(3,1)=1,说明V3与V1直接相连,具体算法是建立一个表,Vi为头,以Vj为尾,如果D(i.j)=j则完结,否则Vh=Vi,VkO=Vj转(2)如果k(m)=D(h,k(m),装(4),否则转(3)k(m+1)=D(h,k(m)把Vk(m+1)插在Vh,Vk(m)之间,返(2)如果k(m)=j
51、,则完结,否则Vh=Vk(m),Vk(m)=Vk(m-1);mm7z如上图经过图中搜索可得到一条较长的道路是从V8到V200,依次经过的顶点为8,21,22,27,28,29,51,62,83,90,100,110,126,136,151,150,164,177,178,179,180,181,182,185,195,197,200弗洛伊德Floyd算法思想:递推地产生一个矩阵序列dist(0)dist(1)dist(n)其中dist(0)=costcost为邻接矩阵元素dist(0)i,j表示从顶点Vi到顶点Vj,中间经过的顶点序号0(即不经任何其他顶点)的最短路径长度。最后dist(n)i
52、,j表示从vi到vj中间经过的顶点序号不大于n的最短路径长度。即为所求。dist(k)i,j是从vi到vj的中间经过顶点序号k的最短路k型最短路。dist(0)(i,j)=cost(i,j)dist(k)(i,j)=mindist(k-1)(i,j),dist(k-1)(i,k)+dist(k-1)(k,j)voidFloyd(GraphG,cost,path)for(i=1;i=n;i+)/dist,pathfor(j=1;j=n;j+)distij=costij;if(distij32767)pathij=Vi+Vj;for(k=1;k=n;k+)/递推产生dist序列for(i=1;i=n;i+)for(j=1;j=n;j+)if(distik+distkjdistij=distik+distkj;pathij=pathik+pathkj;注意:Floyd算法中一种标准错误写法:请注意floyed算法的本质是动态规划!定义f(i,j,k)表示只用第0i个点从j走到k所用的最短路程。f(i,j,k)=min(f(i-1,j,k),f(i-1,j,i)+f(i-1,i,k)所以应该是for(inti=0;isz
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2025年上半年中国矿业大学资源与地球科学学院江苏省能源国际限公司工程技术人员招聘易考易错模拟试题(共500题)试卷后附参考答案
- 2025年上半年中国卫星网络集团限公司度公开招聘易考易错模拟试题(共500题)试卷后附参考答案
- 2025年上半年中国东方航空武汉限责任公司校园招聘若干人易考易错模拟试题(共500题)试卷后附参考答案
- 2024-2025学年湖北省新高考联考协作体高一上学期12月月考历史试卷(解析版)
- 2024-2025学年甘肃省天水市第二中学、新梦想高考复读学校高三上学期12月月考历史试题(解析版)
- 《游子吟》公开课教案
- 衣服编织知识培训课件
- 2025年聚砜PSF项目发展计划
- 2025年空气净化装置:尾气处理装置合作协议书
- 产假申请书范文
- 辽宁省五校联考2024-2025学年高二上学期期末英语试卷(解析版)
- 2024年中考模拟试卷数学(新疆卷)
- 2025年湖南食品药品职业学院高职单招职业技能测试近5年常考版参考题库含答案解析
- 2025年泰山职业技术学院高职单招数学历年(2016-2024)频考点试题含答案解析
- 近岸海上柔性光伏支架结构研究
- 2025年广西投资集团有限公司招聘笔试参考题库含答案解析
- 2024年华北电力大学辅导员及其他岗位招聘考试真题
- 2024年湖北省烟草专卖局(公司)招聘考试真题
- 青岛版科学四年级下册《认识太阳》课件
- 校园法制安全教育第一课
- 李白《关山月》古诗词课件
评论
0/150
提交评论