梦想赌坊的当家(EmilMatthew的侠意人生)

博客已转移至http://www.douban.com/people/emilmatthew/

原创 启发式搜索算法引论------A*算法理论与实践收藏

  启发式搜索算法引论------A*算法理论与实践

            EmilMatthew (EmilMatthew@126.com)      

[  类别  ]算法实践 ,人工智能

[推荐指数]★★★★★

[  摘要  ]本文介绍了启发式算法中一种重要而有效的算法------A*算法的理论,并给出了寻路问题的交互式实现。

[ 关键词 ] A*,启发式算法,最优路径,交互式,AS2

 

Introduction to Heuristics Search------

A* Algorithm Principle and Practice

[Classify] Algorithm Implementation ,  Artificial Intelligence

[  Level ] ★★★★★

[Abstract] This article introduces an important and effective heuristics algorithm ------ A* algorithm with its theory and also gives out its interactive implementation of path finding problem.

[Key Words] A* , Heuristics Algorithm , Best Path Finding , Interactive , AS2

 

 

[1历史回顾]

       P. E. Hart , N. J. Nilsson B. Raphael共同发表了一篇在启发式搜索方面有深远影响力的论文:

“P. E. Hart, N. J. Nilsson, and B. Raphael. A formal basis for the heuristic determination of minimum cost paths in graphs. IEEE Trans. Syst. Sci. and Cybernetics, SSC-4(2):100-107, 1968”。从此,一种精巧、高效的算法------A*算法横空出世了,并在相关领域得到了广泛的应用。

                      

                                  Peter E. Hart                 Nils J. Nilsson

 

[2DFSBFS中来]

   A*算法的思想来源并不是什么高深莫测的东西,事实上,它与我们所熟悉的另外两种搜索策略:DFS(深度优先Deep First Search)和 BFS(广度优先Breadth First Search)有着自然而紧密的联系。

       首先要提一下搜索树的概念,一个可以搜索出某个可行解的问题,如“农夫、白菜、羊、狼”和“八皇后”等,虽然从表面上看上去和“树”这种结构无关,但是整个搜索过程中的可能试探点所行成的搜索空间总可以对应到一颗搜索树上去。所以,将各类形式上不同的搜索问题抽象并统一成为搜索树的形式,为算法的设计与分析带来巨大的方便。

 

下面,让我们通过两个Flash演示来回顾一下DFSBFS的算法思想:

       DFS算法思想演示:

                         

      

 BFS算法思想演示

                         

      

 

      重点要在这里说明是:

       DFSBFS在展开子结点时均属于盲目型搜索,也就是说,它不会选择哪个结点在下一次搜索中更优而去跳转到该结点进行下一步的搜索。在运气不好的情形中,均需要试探完整个解集空间, 显然,只能适用于问题规模不大的搜索问题中。

       那么,作为启发式算法中的A*算法,又比它们高效在哪里呢?

       首先要来谈一下什么是启发式算法。所谓启发式搜索,与DFSBFS这类盲目型搜索最大的不同,就在于当前搜索结点往下选择下一步结点时,可以通过一个启发函数来进行选择,选择代价最少的结点作为下一步搜索结点而跳转其上(遇到有一个以上代价最少的结点,不妨选距离当前搜索点最近一次展开的搜索点进行下一步搜索)。一个经过仔细设计的启发函数,往往在很快的时间内就可得到一个搜索问题的最优解,对于NP问题,亦可在多项式时间内得到一个较优解。

       A*算法,作为启发式算法中很重要的一种,被广泛应用在最优路径求解和一些策略设计的问题中。而A*算法最为核心的部分,就在于它的一个估值函数的设计上:

f(n)=g(n)+h(n)

       其中f(n)是每个可能试探点的估值,它有两部分组成:一部分为g(n),它表示从起始搜索点到当前点的代价(通常用某结点在搜索树中的深度来表示)。另一部分,即h(n),它表示启发式搜索中最为重要的一部分,即当前结点到目标结点的估值,h(n)设计的好坏,直接影响着具有此种启发式函数的启发式算法的是否能称为A*算法。

       一种具有f(n)=g(n)+h(n)策略的启发式算法能成为A*算法的充分条件是:

1)      搜索树上存在着从起始点到终了点的最优路径。

2)      问题域是有限的。

       3)所有结点的子结点的搜索代价值>0

       4h(n)=<h*(n) h*(n)为实际问题的代价值)。

       当此四个条件都满足时,一个具有f(n)=g(n)+h(n)策略的启发式算法能成为A*算法,并一定能找到最优解。([1]P89给出了相关的证明)

对于一个搜索问题,显然,条件1,2,3都是很容易满足的,而

条件4) h(n)<=h*(n)是需要精心设计的,由于h*(n)显然是无法知道的,

所以,一个满足条件4)的启发策略h(n)就来的难能可贵了。不过,对于图的最优路径搜索和八数码问题,有些相关策略h(n)不仅很好理解,而且已经在理论上证明是满足条件4)的,从而为这个算法的推广起到了决定性的作用。不过h(n)距离h*(n)的呈度不能过大,否则h(n)就没有过强的区分能力,算法效率并不会很高。对一个好的h(n)的评价是:h(n)h*(n)的下界之下,并且尽量接近h*(n).

       当然,估值函数的设计也就就仅仅是f(n)=g(n)+h(n)一种,另外的估值函数“变种”如:f(n)=w*g(n)+(1-w)*h(n) f(n)=g(n)+h(n)+h(n-1)针对不同的具体问题亦会有不同的效果。

 

[3A*算法的核心过程]

让我们先来通过两个Flash演示,来看一下A*算法在具体应用时的搜索树是如何展开的。

            

                                                A* Search搜索树1

 

 

                                             

A* Search搜索树2

 

通过演示,我们可以看出:A*算法最为核心的过程,就在每次选择下一个当前搜索点时,是从所有已探知的但未搜索过点中(可能是不同层,亦可不在同一条支路上),选取f值最小的结点进行展开。而所有“已探知的但未搜索过点”可以通过一个按f值升序的队列(即优先队列)进行排列。这样,在整体的搜索过程中,只要按照类似广度优先的算法框架,从优先队列中弹出队首元素(f值),对其可能子结点计算ghf值,直到优先队列为空(无解)或找到终止点为止。

       A*算法与广度优先和深度优先的联系就在于,当g(n)=0时,该算法类似于DFS,当h(n)=0时,该算法类似于BFS , 这一点,可以通过上面的A*搜索树的具体过程中将h(n)设为0或将g(n)设为0而得到。

 

       A*算法实现框架:

       重要数据解释:

       Open Table  :存放所有已探知的但未搜索过点的优先队列。

       Closed Table :存在搜索过的点的数组,提取最优路径时有用。

Start Node   :起始点。

Target Node  :终止点。

C Node      :当前点。

 

       算法框架如下:

1.Init start node , add it to open table

While not reach target node && open table is unNull

       2.a) Get the head node in open table->c node

       2.b) Finding all c node’s possible child node.

       2.c) Calculate each child node’s f value.

       2.d) Remove c node from open table , add it to closed table.

        2.e) Add all c node’s child nodes to open table in an undescend sequence.

Wend

3.Ouput Search Result

      

       算法的实现部分参附录1(C Version),附录2(AS2 Version)

       提取最优路径的算法并不复杂,虽然在CLOSE表中会有许多无效的搜索点,但是最优路径上各结点的下标一定是按照CLOSE表中下标的升序排列的。因此,只要在CLOSE表中,将下标从终止点向起始点移动,若CLOSE[i+1]CLOSE[i]没有关联,则剔除CLOSE[i]

 

[3A*算法在路径最优问题的交互式示例]

       路径最优问题,简单来说,就是在两个结点之间找一条最短路径。有的朋友不禁要问,这个问题不是已经有Dijkstra算法可以解决了吗?此话不假,但是不要忘了Dijkstra算法的复杂度是O(n^2),一旦结点很多并且需要实时计算的话,Dijkstra就无法满足要求了。而A*来处理这类有需要实时要求的问题则显得游刃有余。

       在路径最优问题中,用来作为启发函数关键部分的h(n)其实很容易选,那便是当前结点至最终结点的距离,这个距离既可以是Hamilton距离(|x1-x2|+|y1-y2|),亦可以是Euclid 距离(直线距离)。都可以在较快的速度下达到问题的最优解。

       下面给出在Flash平台下,用AS2编制的交互式A*算法寻路问题的三个示例程序:(限于Flash的处理性能,当你点了一个目标点后,需要等卡通人物行进到该点时方可点下一点)

                                               

                                                            A* Test1

                                               

 

A* Test2

                                                            A* Test3

 

注:上面所示的三个Flash的最优路径搜索有时会出现走弯路的现象,系我这里的最优路径提取算法设计不佳所致(A*算法本身并没有错误),相应的改进请参考:A*算法最优解提取算法

 

      

[4]小结

       本文不仅对A*算法的思想来源及核心部分作了较为详细的介绍,更重要的是,给出了A*算法在网络平台下的一种交互式实现,这一点具有创新意义。

       这个程序的实现,不仅给我自己带去了快乐,相信也带给了更多朋友一点小小的启发,对此,我深感颀慰。当然,这个程序还可以在时实交互性上做得更好些,这是值得努力的方向。还有,A*算法本身亦有许多改进之处,如应对“陷井”时,如何更快的脱离,避免无畏的搜索,都是值得去展开的方向。

 

[参考文献与网站]

[0] 林尧瑞、马少平著,人工智能导论,清华大学出版社,2001.

[1] Nils J.Nilsson著,郑扣根等译,人工智能,机械工业出版社,2003

[2] http://ai.stanford.edu/users/nilsson/trweb/tr.html

[3] http://www.crc.ricoh.com/~hart/

[4] http://i11www.iti.uni-karlsruhe.de/~fschulz/shortest-paths/

程序完成日:06/10/15

文章完成日:06/10/17

 

附录[0]

A*算法核心部分之C语言版本:

       void parseMap_AStar()

       {            

                            float tempG,tempF;

                            EPQ_DataType    tempPoint;

                            int   noFindingFlag;

                            int   i;

                            int   moreThanOneBlock;

                            int   sIndex;

                            currentPoint=startPoint;

                                                                            

                            //early check

                            enQueue_EPQ(testQueue,currentPoint,LESS_THAN_VAL);

                     if(currentPoint->x==targetPoint->x&&

currentPoint->y==targetPoint->y)

                                          goto LABEL_FOUNDED;

                           

                            //Init for output data

                            CTCIndex=0;

                            NAIndex=0;

                            noFindingFlag=0;

                            moreThanOneBlock=0;

                            sIndex=0;

 

                            //core algorithm

                            while(!isEmpty_EPQ(testQueue))

                            {                                 

                               currentPoint=deQueue_EPQ(testQueue);

                                                 

                               //For natrual A* path finding answer output       

                                                                                     CLOSETable[CTCIndex].x=currentPoint->pX;

                               CLOSETable[CTCIndex].y=currentPoint->pY;

                                                                    NATable[NAIndex]=CLOSETable[CTCIndex];

                               CTCIndex++;NAIndex++;

                                                                                                               

             

                     //from current point ,look for the possible point to move.

                     //start from west ,clockwise

                     tempG=currentPoint->g+STEP_G;

                                                       

//west                                            

if(currentPoint->x>1&&

mapData[(int)currentPoint->y][(int)currentPoint->x-1]!=BLOCKED_GROUND&&

mapData[(int)currentPoint->y][(int)currentPoint->x-1]!=LABELED)

{            

                        //target pos check if(currentPoint->x-1==targetPoint->x&&

currentPoint->y==targetPoint->y)

{ currentPoint->pX=currentPoint->x;

currentPoint->pY=currentPoint->y;

currentPoint->x=currentPoint->x-1;

                                                                                                                                                                        goto LABEL_FOUNDED;

                            }

                                                                      tempF=calDis(currentPoint->y,currentPoint->x-1);

                                                                      tempPoint=createAPoint(currentPoint->x-1,currentPoint->y);

       tempPoint->pX=currentPoint->x;

       tempPoint->pY=currentPoint->y;

                                                                                                 

                                                                      setAStarValue(tempPoint,tempF,tempG);

                                                                                                                                            enQueue_EPQ(testQueue,tempPoint,LESS_THAN_VAL);

                                                                                                                              mapData[(int)currentPoint->y][(int)currentPoint->x-1]=LABELED;

}

                                         

//north

if(currentPoint->y>1&&

mapData[(int)currentPoint->y-1][(int)currentPoint->x]!=BLOCKED_GROUND&&

mapData[(int)currentPoint->y-1][(int)currentPoint->x]!=LABELED)

{                                                  

       //target pos check                                                                if(currentPoint->x==targetPoint->x&&

currentPoint->y-1==targetPoint->y)

{                                                                             currentPoint->pX=currentPoint->x;

              currentPoint->pY=currentPoint->y;

              currentPoint->y=currentPoint->y-1;  

              goto LABEL_FOUNDED;

       }

                                                               tempF=calDis(currentPoint->y-1,currentPoint->x);

                                                                                                                                     tempPoint=createAPoint(currentPoint->x,currentPoint->y-1);

       tempPoint->pX=currentPoint->x;

tempPoint->pY=currentPoint->y;

                                                                                                                       setAStarValue(tempPoint,tempF,tempG);

                                                                                    enQueue_EPQ(testQueue,tempPoint,LESS_THAN_VAL);

                                                                                                                       mapData[(int)currentPoint->y-1][(int)currentPoint->x]=LABELED;

}

                                                       

//east                                             

if(currentPoint->x<mapWidth-1&&

mapData[(int)currentPoint->y][(int)currentPoint->x+1]!=BLOCKED_GROUND&&

mapData[(int)currentPoint->y][(int)currentPoint->x+1]!=LABELED)

{

       //target pos check                                                         if(currentPoint->x+1==targetPoint->x&&

currentPoint->y==targetPoint->y)

       {

              currentPoint->pX=currentPoint->x;

              currentPoint->pY=currentPoint->y;

              currentPoint->x=currentPoint->x+1;

                                                                     

              goto LABEL_FOUNDED;

       }

                                                               tempF=calDis(currentPoint->y,currentPoint->x+1);                                          tempPoint=createAPoint(currentPoint->x+1,currentPoint->y);

       tempPoint->pX=currentPoint->x;

       tempPoint->pY=currentPoint->y;

                                                                                                                                     setAStarValue(tempPoint,tempF,tempG);                                                                     

       enQueue_EPQ(testQueue,tempPoint,LESS_THAN_VAL);

                                                                     

       mapData[(int)currentPoint->y][(int)currentPoint->x+1]=LABELED;

}

                                                       

//south                                                 

if(currentPoint->y<mapHeight-1&&

mapData[(int)currentPoint->y+1][(int)currentPoint->x]!=BLOCKED_GROUND&&

mapData[(int)currentPoint->y+1][(int)currentPoint->x]!=LABELED)

{

       //target pos check                                                         if(currentPoint->x==targetPoint->x&&

currentPoint->y+1==targetPoint->y)

{                                                     

currentPoint->pX=currentPoint->x;

currentPoint->pY=currentPoint->y;

currentPoint->y=currentPoint->y+1;

                                                                                                                          goto LABEL_FOUNDED;

         }

                                                        tempF=calDis(currentPoint->y+1,currentPoint->x);

                                                                                    tempPoint=createAPoint(currentPoint->x,currentPoint->y+1);

       tempPoint->pX=currentPoint->x;

       tempPoint->pY=currentPoint->y;                                                              

                                                                                                                                     setAStarValue(tempPoint,tempF,tempG);

                                                                                                                       enQueue_EPQ(testQueue,tempPoint,LESS_THAN_VAL);

                                                                                                                              mapData[(int)currentPoint->y+1][(int)currentPoint->x]=LABELED;

}                                 

}

                                                              

LABEL_FOUNDED:

                     CLOSETable[CTCIndex].x=currentPoint->pX;

                     CLOSETable[CTCIndex].y=currentPoint->pY;

                     NATable[NAIndex]=CLOSETable[CTCIndex];

                     CTCIndex++;NAIndex++;

                     CLOSETable[CTCIndex].x=currentPoint->x;

                     CLOSETable[CTCIndex].y=currentPoint->y;

                     NATable[NAIndex]=CLOSETable[CTCIndex];

                     CTCIndex++;NAIndex++;

      

                     //PROCESS OF ANSTable.

                     ANSTable[0]=CLOSETable[CTCIndex-1];

                     ANSIndex=1;

                           

                     i=CTCIndex-2;

do

{

       //ARBITARY OF NEAR BY POINT

if(

(CLOSETable[i].x-1==ANSTable[ANSIndex-1].x&&CLOSETable[i].y==ANSTable[ANSIndex-1].y)||

(CLOSETable[i].x==ANSTable[ANSIndex-1].x&&CLOSETable[i].y-1==ANSTable[ANSIndex-1].y)||

(CLOSETable[i].x+1==ANSTable[ANSIndex-1].x&&CLOSETable[i].y==ANSTable[ANSIndex-1].y)||

(CLOSETable[i].x==ANSTable[ANSIndex-1].x&&CLOSETable[i].y+1==ANSTable[ANSIndex-1].y))

              {

                                   ANSTable[ANSIndex]=CLOSETable[i];

                                   ANSIndex++;     

               }

                                    

              i--;

}while(!(CLOSETable[i].x==startPoint->x&&CLOSETable[i].y==startPoint->y));

                    

              //Output CLOSE table and NATRUAL table … …

       }

附录[1]

A*算法核心部分之AS2语言版本:

function AStarSearch():Void

{

              if(_root.gStartX==_root.gEndX&&_root.gStartY==_root.gEndY)

                     return;

              else

              {     

                       AStarQueue=new eQueue();

                           

                       targetNode=new eNode();

                       currentNode=new eNode();

                       tempNode=new eNode();

                                  

                                                

                            //a)data init

                            NAIndex=0;

                            CTCIndex=0;

                            FrameNAIndex=0;

                            ParTableIndex=0;

      

                            STEP_G=0.5;

                           

                            noFindingFlag=0;

                            moreThanOneBlock=0;

                            sIndex=0;

                                  

                                                       

                            targetNode.setXY(_root.gEndX,_root.gEndY);

                            currentNode.setXY(_root.gStartX,_root.gStartY);

                           

                            _root.gMapArr[_root.gStartY][_root.gStartX]=LABELED;

                           

                            currentNode.pX=-1;currentNode.pY=-1;

                              currentNode.setG_H(0,Cal_Cost(currentNode,targetNode));

                           

                            AStarQueue.enQueue_AStar(currentNode);

                           

//b)core algorithm

                           

                            while(!AStarQueue.isEmpty())

                            {

                                           

                                   currentNode=AStarQueue.deQueue();

                                                        

                                   //For natrual A* path finding answer output       

                                                               

                               CLOSETable[CTCIndex]=new eNode();

                               CLOSETable[CTCIndex].x=currentNode.x;

                                   CLOSETable[CTCIndex].y=currentNode.y;

                                   CTCIndex++;

                                                              

                                   ParTable[ParTableIndex]=new eNode();

                                   ParTable[ParTableIndex].x=currentNode.pX;

                                   ParTable[ParTableIndex].y=currentNode.pY;

                                   ParTableIndex++;

                                                              

                            //from current point ,look for the possible point to move.

                            //start from west ,clockwise

                                   tempG=currentNode.mG+STEP_G;

                                                       

//west                                     

if(currentNode.x>1&&

_root.gMapArr[currentNode.y][currentNode.x-1]!=BLOCKED_GROUND&&

_root.gMapArr[currentNode.y][currentNode.x-1]!=LABELED)

       {                                                                                  

//target pos check

                                                                      if(currentNode.x-1==targetNode.x&&currentNode.y==targetNode.y)

              {

                     currentNode.pX=currentNode.x;

                     currentNode.pY=currentNode.y;

                     currentNode.x=currentNode.x-1;

                                                                         break;

              }

                                                              

              tempNode=new eNode();

                                         

      tempNode.setXY(currentNode.x-1,currentNode.y);

                                                                            

              tempH=Cal_Cost(targetNode,currentNode);

              tempNode.pX=currentNode.x;

              tempNode.pY=currentNode.y;

                                                                                                 

              tempNode.setG_H(tempG,tempH);

                                                                                                                                                   AStarQueue.enQueue_AStar(tempNode);

                                                                                                                                                _root.gMapArr[currentNode.y][currentNode.x-1]=LABELED;

       }

                                         

//north                                                  

if(currentNode.y>1&&

_root.gMapArr[currentNode.y-1][currentNode.x]!=BLOCKED_GROUND&&

_root.gMapArr[currentNode.y-1][currentNode.x]!=LABELED)

{

       //target pos check                                                         if(currentNode.x==targetNode.x&&currentNode.y-1==targetNode.y)

       {

                     currentNode.pX=currentNode.x;

                     currentNode.pY=currentNode.y;

                     currentNode.y=currentNode.y-1;

                                                                                   

                     break;

       }

 

       tempNode=new eNode();

                                                                      tempNode.setXY(currentNode.x,currentNode.y-1);

                                                                     

                                                                      tempH=Cal_Cost(targetNode,tempNode);

       tempNode.pX=currentNode.x;

       tempNode.pY=currentNode.y;                                                                

       tempNode.setG_H(tempG,tempH);

                                                                                                                                     AStarQueue.enQueue_AStar(tempNode);

                                                                                                                                            _root.gMapArr[currentNode.y-1][currentNode.x]=LABELED;

}

                                                       

//east

                                  

if(currentNode.x<_root.gColNum-1&&

_root.gMapArr[currentNode.y][currentNode.x+1]!=BLOCKED_GROUND&&_root.gMapArr[currentNode.y][currentNode.x+1]!=LABELED)

{

                                                                     

       //target pos check                                                                if(currentNode.x+1==targetNode.x&&currentNode.y==targetNode.y)

       {

                            currentNode.pX=currentNode.x;

                            currentNode.pY=currentNode.y;

                                                                                                          currentNode.x=currentNode.x+1;

                                                                                                                             

                            break;

       }

 

tempNode=new eNode();                                                             tempNode.setXY(currentNode.x+1,currentNode.y);                                    tempH=Cal_Cost(targetNode,tempNode);

       tempNode.pX=currentNode.x;

       tempNode.pY=currentNode.y;

                                                                                                                                    

       tempNode.setG_H(tempG,tempH);

                                                                                                                                            AStarQueue.enQueue_AStar(tempNode);

                                                                                                                                            _root.gMapArr[currentNode.y][currentNode.x+1]=LABELED;

                                                                     

}

                                                       

//south       

                                                              

                                                

if(currentNode.y<_root.gRowNum-1&&

_root.gMapArr[currentNode.y+1][currentNode.x]!=BLOCKED_GROUND&&

_root.gMapArr[currentNode.y+1][currentNode.x]!=LABELED)

       {

              //target pos check                                                         if(currentNode.x==targetNode.x&&currentNode.y+1==targetNode.y)

              {

                                   currentNode.pX=currentNode.x;

                                currentNode.pY=currentNode.y;

                                   currentNode.y=currentNode.y+1;

                                                                                                                             

                                   break;

              }

                    

                tempNode=new eNode();                             

tempNode.setXY(currentNode.x,currentNode.y+1);

           tempH=Cal_Cost(tempNode,targetNode);

             

tempNode.pX=currentNode.x;

              tempNode.pY=currentNode.y;

                                                                                                 

              tempNode.setG_H(tempG,tempH);

                                                                                                                                    

              AStarQueue.enQueue_AStar(tempNode);

                                                                                                                                                   _root.gMapArr[currentNode.y+1][currentNode.x]=LABELED;

       }

}

 

//FINISHED_LABEL:

                                   CLOSETable[CTCIndex]=new eNode();

                                   CLOSETable[CTCIndex].x=currentNode.x;

                                   CLOSETable[CTCIndex].y=currentNode.y;

                                   CTCIndex++;

                                                              

                                   ParTable[ParTableIndex]=new eNode();

                                   ParTable[ParTableIndex].x=currentNode.pX;

                                   ParTable[ParTableIndex].y=currentNode.pY;

                                   ParTableIndex++;

                    

                    

                     //PROCESS OF NATable.

                     NATable[0]=new eNode();

                     NATable[0]=CLOSETable[CTCIndex-1];

                     NAIndex=1;

                    

                     trace3("NATable[0]"+"("+String(NATable[0].x)+","+String(NATable[0].y)+")\n");

                    

                     //Assertion 

                     if(CTCIndex!=ParTableIndex)

                     {

                                   trace3("in a star search:CTCIndex!=ParTableIndex");

                                   return;

                     }      

                    

                     i=CTCIndex-1;

                    

                     do

                     {

                                   NATable[NAIndex]=new eNode();

                                   NATable[NAIndex]=ParTable[i]; 

                                   NAIndex++;

                                   i--;

                                  

                                   if(i==0)//normal successful exit pos

                                          break;

                                  

                     while(!(NATable[NAIndex-1].x==CLOSETable[i].x&&

NATable[NAIndex-1].y==CLOSETable[i].y))

                                   {

                                          i--;

                                   }

                    

                                   if(i==0)//special condition exit pos

                                   {

                                          NATable[NAIndex]=new eNode();

                                          NATable[NAIndex]=CLOSETable[i];   

                                          NAIndex++;

                                         

                                          break;

                                   }

                     }while(true);      

 

                     var timeCount:Number=0;

                     var midObj:eNode;

                    

                     if(NAIndex%2==0)

                            timeCount=NAIndex/2;

                     else

                            timeCount=(NAIndex-1)/2;

                    

                     for(i=0;i<timeCount;i++)

                     {

                                   midObj=new eNode();      

                                   midObj=NATable[i];

                                   NATable[i]=NATable[NAIndex-1-i];

                                   NATable[NAIndex-1-i]=midObj;

                     }

                           

              }

}

 

 

[源码下载、源程序下载]

源程序内容列表:

Code1:C语言版本源码

Code2:AS2版本源码

http://emilmatthew.51.net/EmilPapers/0632AStarSearch/code1.rar

http://emilmatthew1984.googlepages.com/0633code2.rar

 

若直接点击无法下载(或浏览),请将下载(或浏览)的超链接粘接至浏览器地( 推荐MYIE或GREENBORWSER)址栏后按回车.若不出意外,此时应能下载.

若下载中出现了问题,请参考:

http://blog.csdn.net/emilmatthew/archive/2006/04/08/655612.aspx

 

发表于 @ 2006年10月17日 23:15:00|评论(loading...)

新一篇: A*算法最优解提取算法 | 旧一篇: Speech:Intorduction to Heuristics Algorithm------A* Algorithm

用户操作
[即时聊天] [发私信] [加为好友]
秦盛
订阅我的博客
XML聚合  FeedSky
订阅到鲜果
订阅到Google
订阅到抓虾
秦盛的公告

〖我的作品〗



〖我的连载〗

快速Flash开发

〖文化视角〗

     1.90年代初的苏州

     2.中国动画80年

     3.古城真定

     4.三国知识问答

     5.大哥陈松勇

     6.圣斗士.终章

     7.武侠配乐.少林雄风

     8.李宗盛.生活家的院子

     9.李敖精彩语录选

     10.安东尼奥尼.中国.剪影.1

     11.安东尼奥尼.中国.剪影.2

     12.林青霞向季老讨文气

     13.山水情.中国水墨动画之巅峰

     14.《人物》之媒体人.刘长乐

     15.侯孝贤谈悲情城市

     16.转.夜泊秦淮近酒家

     17.冯骥才:守望民间文化的精卫鸟


我是一个快乐的赌徒,因为我掷出去的每把骰子,都是自己的,玩的都是真性情。


和很多人一样,我没有好的家境可以依赖,一切都从零开始,靠自己打拼.有时,站在太阳下,经常问自己:"我就这样了?"回答,当然是否定的,但要的是------行动.



〖宣言〗

前途是光明的

道路是曲折的


〖祈福〗

祝季羡林老先生在301医院身体健康,心情愉快!

祝李敖大师精神矍铄,风采不逊当年,多出新作!

遥祝Bertrand Rusell在天堂依旧幸福人生!


    〖强烈推荐〗

   ACM图灵奖演讲集

   FF背后的牛人们

   (视频)Dijkstra风采













文章分类
收藏
05大师有大智慧
Alan Kay(Smalltalk,OOP)
BERTRAND RUSSELL
Donald E. Knuth(Art of Algorithm)
Edsger W. Dijkstra(Programming & Algorithm Design,Shortest Path)
John McCarthy(人工智能)
李敖
06闲情,感悟
苏州古城的历史
苏州杂志
读者论坛
赵云庙
07天籁之音
[周华健,李度]难以抗拒
[成龙,苏慧伦]在我生命中的每一天
[成龙]壮志在我胸
[灌篮高手]直到世界的尽头
Somewhere out there
somke gets in your eyes
When You Believe
野风[新龙门客栈片尾曲,林忆莲]
08苏州中学
苏中主页
09算法,数据结构,优化
ACM/ICPC的司令部
Dictionary of Algo&DS
IOI选手优秀论文
Lucky猫的ACM园地
UVA在线答题系统
中国人工智能网
中国数据挖掘网
中国网格信息中转站
中国运筹学协会
信息学初学者之家
信息学奥林匹克基地
北大ACM站
数据结构自考网
浙大ACM站
10科学,论文
Citeseer
Scientific American
Tex中文站
yesize资料坊
上海网上天文台
中国学术期刊网
中国工程院
中国水利期刊
中国知网
中国科学院
大众科普网
奇迹文库
科研中国
集智俱乐部
11名校计算机科学院巡礼
(UIUC)伊利诺伊香槟分校
Carnegie Mellon(卡梅基隆)
Mit[麻省理工学院]
Princeton[普灵斯顿大学]
purdue[普度大学]
Stanford[斯坦福大学]
中国科学技术大学
交通大学
北京大学
南京大学
复旦大学
浙江大学
清华大学
12应用数学,建模
Math.com
中国数学建模
中国统计网
数学中国
数学常用工具FAQ
13ComputerScience
《计算机教育》期刊网站
acm来了
李开复学生网
15综合科学
《科学》杂志
从欧氏几何到微分几何
16数值计算
Pi的小站
17朋友的链接
Nemon
大漠穷秋
18EnglishLearning
沪江英语
20图形学
The Chaos Games
VRML用户手册
中国虚拟现实开发者
中国计算机图形学教学研究会
分形屏道
分形艺术
机器视觉在线
虚拟无忌
21操作系统
Bochs摸拟环境
ChinaLinux
Linux/BSD/UNIX文档
Linux_Kernel
中国UNIX技术联盟
帮助Linux爱好者
永远的UNIX
22ActionScript_Flash
[Flasher]Dengjie
[开源的AS2编译器]Mtasc
FlashASM
RobertPenner
ultrashock
X-Woods
闪吧音乐盒
23C/C++
C++ Home
C++FAQ-LITE
C-C++ User Journal
CPlusPlus.com
C语言之家
GCC Compiler
GCC.GNU
SGI-STL
VCHelp[CN DEV]
VC知识库
24GameDev
CSDN游戏开发站
GamaSutra
GameAI
GameDev.NET
Gamerers
vbgamer
25JAVA技术
JAVA.SUN
中文JAVA技术网
26编程技术
[MSDN Eng]
[MSDN 中文版]
ASCII Table
SourceForge
UML.ORG
中国程序员(CSDN)
文件格式汇编
程序员联合开发网
问专家
28物理模拟与仿真
中国仿真互动
流体中文网
29网络安全
绿盟论坛
30环保
中国环境监测
南水北调网
国家环保总局
江苏环保网
31可爱的事物
叮铛论坛
32设计,排版
5D多媒体
BlueIdea
印科网
33影视,音乐,电台
上海文广新闻传媒
阿拉上海人
34优秀个人BLOG
fisher_jiang的专栏
gzfqh的专栏
ScienceStudy
刘爱贵的个人主页
大肚能容天下剑
寒蝉退士
梦想风暴
煮石
男儿当自强
男单618
编程夜未眠
记得忘记@博客
35专栏
抗战胜利60年(sina)
抗战胜利60年(yahoo)
50电子游戏
Raine街机模拟器
WAR3中文网
专业射击游戏联盟
地精研究院
51常用软件
flashfxp
GreenBrowser
小巧好用的编辑器SciTEFlash
强力抓屏
金山在线词典
52网上书店
DearBook
当当网
53硬件DIY
52硬件
电脑报论坛
存档
Csdn Blog version 3.1a
Copyright © 秦盛