启发式搜索A星算法
A-star算法

A*算法
A* [1](A-Star)算法是一种静态路网中求解最短路径最有效的直接搜索方法,也是许多其他问题的常用启发式算法。
注意——是最有效的直接搜索算法,之后涌现了很多预处理算法(如ALT,CH,HL等等),在线查询效率是A*算法的数千甚至上万倍。
公式表示为:f(n)=g(n)+h(n),
其中,f(n) 是从初始状态经由状态n到目标状态的代价估计,
g(n) 是在状态空间中从初始状态到状态n的实际代价,
h(n) 是从状态n到目标状态的最佳路径的估计代价。
(对于路径搜索问题,状态就是图中的节点,代价就是距离)
h(n)的选取
保证找到最短路径(最优解的)条件,关键在于估价函数f(n)的选取(或者说h(n)的选取)。
我们以d(n)表达状态n到目标状态的距离,那么h(n)的选取大致有如下三种情况:
1. 如果h(n)< d(n)到目标状态的实际距离,这种情况下,搜索的点数多,搜索
范围大,效率低。
但能得到最优解。
2. 如果h(n)=d(n),即距离估计h(n)等于最短距离,那么搜索将严格沿着最短路
径进行,此时的搜索效率是最高的。
3. 如果h(n)>d(n),搜索的点数少,搜索范围小,效率高,但不能保证得到最
优解。
[2]。
a星算法求解八数码问题python

a星算法求解八数码问题python一、介绍八数码问题是一种经典的智力游戏,也是人工智能领域中的经典问题之一。
在这个问题中,有一个3×3的棋盘,上面摆着1至8这8个数字和一个空格,初始状态和目标状态都已知。
要求通过移动数字,将初始状态变换成目标状态。
其中空格可以和相邻的数字交换位置。
为了解决这个问题,我们可以使用A*算法。
本文将详细介绍如何用Python实现A*算法来求解八数码问题。
二、A*算法简介A*算法是一种启发式搜索算法,常用于寻找最短路径或最优解等问题。
它基于Dijkstra算法,并加入了启发式函数来加速搜索过程。
在A*算法中,每个节点都有两个估价值:g值和h值。
g值表示从起点到该节点的实际代价,h值表示从该节点到目标节点的估计代价。
启发式函数f(n) = g(n) + h(n) 表示从起点到目标节点的估计总代价。
A*算法采用优先队列来保存待扩展的节点,并按照f(n)值从小到大排序。
每次取出队头元素进行扩展,并将扩展出来的新节点按照f(n)值插入队列中。
当扩展出目标节点时,算法结束。
三、八数码问题的状态表示在八数码问题中,每个状态都可以表示为一个3×3的矩阵。
我们可以用一个一维数组来表示这个矩阵,其中0表示空格。
例如,初始状态可以表示为[2, 8, 3, 1, 6, 4, 7, 0, 5],目标状态可以表示为[1, 2, 3, 8, 0, 4, 7, 6, 5]。
四、A*算法求解八数码问题的步骤1.将初始状态加入优先队列中,并设置g值和h值为0。
2.从队头取出一个节点进行扩展。
如果该节点是目标节点,则搜索结束;否则,将扩展出来的新节点加入优先队列中。
3.对于每个新节点,计算g值和h值,并更新f(n)值。
如果该节点已经在优先队列中,则更新其估价值;否则,将其加入优先队列中。
4.重复第2步至第3步直到搜索结束。
五、Python实现以下是用Python实现A*算法求解八数码问题的代码:```import heapqimport copy# 目标状态goal_state = [1,2,3,8,0,4,7,6,5]# 启发式函数:曼哈顿距离def h(state):distance = 0for i in range(9):if state[i] == 0:continuerow = i // 3col = i % 3goal_row = (state[i]-1) // 3goal_col = (state[i]-1) % 3distance += abs(row - goal_row) + abs(col - goal_col)return distance# A*算法def A_star(start_state):# 初始化优先队列和已访问集合queue = []visited = set()# 将初始状态加入优先队列中,并设置g值和h值为0heapq.heappush(queue, (h(start_state), start_state, 0))while queue:# 取出队头元素进行扩展f, state, g = heapq.heappop(queue)# 如果该节点是目标节点,则搜索结束;否则,将扩展出来的新节点加入优先队列中。
a星算法栅格大小 -回复

a星算法栅格大小-回复A*算法栅格大小(Grid Size):优化路径规划问题的关键因素引言:在实际生活中,我们经常面临需要找到最优路径的问题,比如在城市中规划最短的驾驶路线,或者在机器人路径规划中找到最节省能量的路径。
为了解决这类问题,A*(A-star)算法被广泛应用。
而A*算法中栅格大小的选择,直接影响到算法的运行效率和结果的准确性。
本文将分步骤详细回答关于A*算法栅格大小问题,帮助读者更好地理解该算法并能灵活应用。
第一步:什么是A*算法?A*算法是一种启发式搜索算法,用于在图形地图或网络中寻找最短路径。
它综合考虑了路径长度和启发函数(估计距离)来选择下一步的移动方向,以达到更高的搜索效率。
第二步:A*算法中的栅格大小是什么意思?在应用A*算法时,地图或网络被划分成多个小方格,每个方格被称为一个栅格。
栅格的大小决定了图形地图或网络的分辨率,直接影响到A*算法的搜索过程和搜索结果。
第三步:如何选择合适的栅格大小?1. 如何确定栅格数:栅格数可以通过将地图或网络的长度和宽度除以栅格的大小得到。
例如,如果地图的长度为100米,宽度为100米,我们选择10x10米的栅格大小,则地图将被划分成10x10个栅格。
2. 如何选择合适的栅格大小:栅格大小的选择应该综合考虑以下几个因素:a. 地图或网络的规模:大地图或网络通常需要较大的栅格,以便更好地表示地图信息,并存储和处理更多的栅格数据。
b. 搜索的精度要求:如果需要精确计算最优路径的长度,应选择较小的栅格大小。
c. 计算资源限制:较大的栅格大小可能会导致更高的计算复杂性和更长的计算时间。
如果计算资源有限,可以选择较大的栅格来降低计算开销。
d. 环境特征:如果地图或网络中存在窄小的路径或拥挤的区域,应选择较小的栅格以更准确地表示这些细节。
第四步:栅格大小对A*算法的影响1. 增加栅格大小的优点:a. 减少计算开销:使用较大的栅格可以降低搜索空间的规模,从而减少计算开销,提高搜索效率。
启发式搜索A星算法

启发式搜索——初识A*算法A*在游戏中有它很典型的用法,是人工智能在游戏中的代表。
A*算法在人工智能中是一种典型的启发式搜索算法,为了说清楚A*算法,先说说何谓启发式算法。
一、何谓启发式搜索算法在说它之前先提提状态空间搜索。
状态空间搜索,如果按专业点的说法,就是将问题求解过程表现为从初始状态到目标状态寻找这个路径的过程。
通俗点说,就是在解一个问题时,找到一个解题的过程,应用这个过程可以从求解的开始得到问题的结果。
由于求解问题的过程中分支有很多,主要是求解过程中求解条件的不确定性、不完备性造成的,使得求解的路径很多,这样就构成了一个图,我们说这个图就是状态空间。
问题的求解实际上就是在这个图中找到一条路径可以从开始到结果。
这个寻找的过程就是状态空间搜索。
常用的状态空间搜索有深度优先和广度优先。
广度优先是从初始状态一层一层向下找,直到找到目标为止。
深度优先是按照一定的顺序,先查找完一个分支,再查找另一个分支,直至找到目标为止。
这两种算法在数据结构书中都有描述,可以参看这些书得到更详细的解释。
前面说的广度和深度优先搜索有一个很大的缺陷就是:他们都是在一个给定的状态空间中穷举。
这在状态空间不大的情况下是很合适的算法,可是当状态空间十分大,且不可预测的情况下就不可取了。
他们的效率实在太低,甚至不可完成。
在这里就要用到启发式搜索了。
启发式搜索就是在状态空间中搜索时,对每一个搜索的位置进行评估,得到最好的位置,再从这个位置进行搜索直至找到目标。
这样可以省略大量无谓的搜索路径,提高了效率。
在启发式搜索中,对位置的估价是十分重要的。
采用了不同的估价可以有不同的效果。
我们先看看估价是如何表示的。
启发中的估价是用估价函数表示的,如:f(n) = g(n) + h(n)其中f(n)是节点n的估价函数,g(n)是在状态空间中从初始节点到n节点的实际代价,h(n)是从n节点到目标节点最佳路径的估计代价。
在这里主要是h(n)体现了搜索的启发信息,因为g(n)是已知的。
astar寻路算法原理

astar寻路算法原理
A(A星)寻路算法是一种常用的启发式搜索算法,用于在图中
找到从起点到终点的最短路径。
它结合了Dijkstra算法和启发式搜
索的优点,具有较高的搜索效率。
A算法基于图的搜索,其中每个节点表示一个状态,边表示从
一个状态到另一个状态的转移。
算法使用两个函数来评估每个节点
的重要性,g(n)表示从起点到节点n的实际代价,h(n)表示从节点
n到终点的估计代价。
A算法通过综合考虑这两个函数来选择下一个
要扩展的节点。
具体来说,A算法通过维护一个开放列表和一个关闭列表来进
行搜索。
它首先将起点加入开放列表,然后重复以下步骤直到找到
终点或者开放列表为空:
1. 从开放列表中选择f(n)=g(n)+h(n)最小的节点n进行扩展。
2. 将节点n从开放列表中移入关闭列表。
3. 对节点n的相邻节点进行检查,更新它们的g值和f值,并
将它们加入开放列表中。
A算法的关键在于如何选择合适的启发函数h(n)以及如何高效地维护开放列表和关闭列表。
合适的启发函数可以大大提高搜索效率,而高效的列表维护可以减少搜索时间。
总的来说,A算法是一种高效的寻路算法,能够在图中找到最短路径,并且可以通过调整启发函数来适应不同的问题。
A星算法

很早以前就写过A*算法,现在把概念写出来供参考寻路一般主要有深度优先和广度优先及启发式探索算法。
a. 深度优先:一般是深度优先是按照一定的顺序前查找完一个分支,再查找另一个分支,直到找到目标或到达步数为止。
b.广度优先一般是找周围所有点记录下来,然后在对每个点找它们周围所有未找过的点,然后再如此循环下去直到找到目标为止。
c. 启发式启发式搜索一般是对每个搜索位置进行评估,找到最好的位置,再从这个位置如此循环进行搜索直到目标。
启发中的估价是用估价函数表示的:f(n) = g(n) + h(n)其中f(n) 是节点n的估价函数,g(n)是从初始点到n结点的实际代价,h(n)是从n结点到目标点最佳路径的估价。
如果公式中的h(n)总是=0, 也即不进行估价,那么就是广度优先,现在的A*算法一般都使用了启发式函数,对于普通的A*算法通常使用当前结点到目标结点的距离来计算h。
关于启发式要考虑的启发因素还有类似于一些地形属性如泥士地走慢点等也可考虑在内。
晕死, 后来发现原来我早之前已经写过这个文章, 见我旧blog:/blog/cns!8E578E7901A88369!444.entry内容如下:寻路备忘录寻路备忘录一.深度优先搜索(DFS)按照一定顺序(如左上右下)能走则走(这就是深度两字的来源),就象一个瞎子走迷宫一样:1.选定一个方向一直走2.碰壁后退一步,再重复1的步骤.缺点:a.在很少障碍的空地图上若跨出的第一步顺序不对时寻路挺费时;b.找到的不一定是最短路径优点:算法所用内存较少.二.广度优先搜索(BFS)1.先在开始位置测试周围一格所能走的路,并记录周围的通路格子;2.然后依次选择周围的通路格子位置重复1步骤.这就象一个水波扩散一样,这就是广度两字的来源.缺点:寻路所用内存较大优点:能保证找到最短路径三.启发式搜索:A*就是常用的一种启发式算法.作法如下:1.选路,这会用到一个叫估价函数的东东F(X),其中F(X)=G(X)+H(X);式中的G(X)一般是已经搜索的步数,而H(X)则是一个从当前节点到目标节点估计函数,一般可用当前节点到目标节点的距离来作比较.2.走路,碰到不通路时,在所有所记录的通路中重新选择一条路来走,即重复1.优点:速度快并且所占内存不多。
A星算法实验报告

A*算法实验报告一、实验原理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。
4)h(n)=<h*(n) (h*(n)为实际问题的代价值)。
当此四个条件都满足时,一个具有f(n)=g(n)+h(n)策略的启发式算法能成为A*算法,并一定能找到最优解。
对于一个搜索问题,显然,条件1,2,3都是很容易满足的,而条件4):h(n)<=h*(n)是需要精心设计的,由于h*(n)显然是无法知道的。
所以,一个满足条件4)的启发策略h(n)就来的难能可贵了。
不过h(n)距离h*(n)的程度不能过大,否则h(n)就没有过强的区分能力,算法效率并不会很高。
对一个好的h(n)的评价是:h(n)在h*(n)的下界之下,并且尽量接近h*(n).二、实验过程运行未修改的程序会得到最优路径为:算法共扩展节点数792.若修改源程序,即允许走斜线则distance=(int)sqrt((end_x-x)*(end_x-x)+(end_y-y)*(end_y-y)),即将估价函数改为欧式距离四连通改为八连通trytile(x,y-1,n,1); //尝试向上移动trytile(x+1,y-1,n,2);// 尝试向前上方移动trytile(x-1,y-1,n,2); // 尝试向后上方移动trytile(x-1,y+1,n,2); // 尝试向后下方移动trytile(x+1,y+1,n,2); // 尝试向前下方移动trytile(x,y+1,n,1); //尝试向下移动trytile(x-1,y,n,1); //尝试向左移动trytile(x+1,y,n,1); //尝试向右移动并修改g值if(lei==1) //如果是直线走{g_value=father->g+1;}if(lei==2) //如果是斜线走{g_value=father->g+1.414;}修改后的扩展结点数837三、实验分析A*算法最为核心的过程,就在每次选择下一个当前搜索点时,是从所有已探知的但未搜索过点中(可能是不同层,亦可不在同一条支路上),选取f 值最小的结点进行展开。
a星算法资料

A星算法A星算法是一种常用的路径规划算法,它可以在很多领域得到应用,如游戏开发、机器人导航等。
本文将介绍A星算法的原理、实现过程以及应用场景。
原理A星算法是一种启发式搜索算法,用于寻找从起点到目标点的最佳路径。
它基于Dijkstra算法和最小堆叠加了启发式因子来加速搜索过程。
A星算法在搜索过程中维护两个集合:开放集合和关闭集合。
开放集合存储待探索的节点,而关闭集合存储已经探索过的节点。
算法的核心思想是维护每个节点的估价函数f值,其中f值由节点到目标点的实际代价g值和节点到目标点的启发函数h值组成。
在每一步中,算法从开放集合中选择f值最小的节点进行拓展,并更新其邻居节点的f值。
实现过程1.初始化起点,并将其加入开放集合中,设置启发函数h值为起点到目标点的估计代价。
2.重复以下步骤直到目标节点被加入关闭集合:–从开放集合中选择f值最小的节点,将其加入关闭集合。
–针对选定节点的每个邻居节点,计算其新的f值并更新。
–如果邻居节点不在开放集合中,将其加入开放集合。
3.构建路径,反向回溯从目标节点到起点的最佳路径。
应用场景•游戏开发:A星算法可以用来实现游戏中的AI寻路,使NPC角色能够智能地避开障碍物。
•机器人导航:A星算法可以帮助机器人避开障碍物,规划出最优的路径来到目标点。
•交通规划:A星算法可以用来优化城市道路的规划,减少交通拥堵,提高车辆通行效率。
•资源调度:A星算法可以帮助企业在多个资源之间寻找最佳路径,提高资源利用率。
总之,A星算法在许多领域都有着广泛的应用,它的高效性和可扩展性使其成为一种非常有力的路径规划工具。
结语A星算法是一种非常经典的路径规划算法,其优秀的性能和广泛的应用使其成为计算机科学领域的重要研究内容。
希望本文介绍的内容对读者有所帮助,让大家更加深入了解A星算法的原理和应用。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
启发式搜索——初识A*算法A*在游戏中有它很典型的用法,是人工智能在游戏中的代表。
A*算法在人工智能中是一种典型的启发式搜索算法,为了说清楚A*算法,先说说何谓启发式算法。
一、何谓启发式搜索算法在说它之前先提提状态空间搜索。
状态空间搜索,如果按专业点的说法,就是将问题求解过程表现为从初始状态到目标状态寻找这个路径的过程。
通俗点说,就是在解一个问题时,找到一个解题的过程,应用这个过程可以从求解的开始得到问题的结果。
由于求解问题的过程中分支有很多,主要是求解过程中求解条件的不确定性、不完备性造成的,使得求解的路径很多,这样就构成了一个图,我们说这个图就是状态空间。
问题的求解实际上就是在这个图中找到一条路径可以从开始到结果。
这个寻找的过程就是状态空间搜索。
常用的状态空间搜索有深度优先和广度优先。
广度优先是从初始状态一层一层向下找,直到找到目标为止。
深度优先是按照一定的顺序,先查找完一个分支,再查找另一个分支,直至找到目标为止。
这两种算法在数据结构书中都有描述,可以参看这些书得到更详细的解释。
前面说的广度和深度优先搜索有一个很大的缺陷就是:他们都是在一个给定的状态空间中穷举。
这在状态空间不大的情况下是很合适的算法,可是当状态空间十分大,且不可预测的情况下就不可取了。
他们的效率实在太低,甚至不可完成。
在这里就要用到启发式搜索了。
启发式搜索就是在状态空间中搜索时,对每一个搜索的位置进行评估,得到最好的位置,再从这个位置进行搜索直至找到目标。
这样可以省略大量无谓的搜索路径,提高了效率。
在启发式搜索中,对位置的估价是十分重要的。
采用了不同的估价可以有不同的效果。
我们先看看估价是如何表示的。
启发中的估价是用估价函数表示的,如:f(n) = g(n) + h(n)其中f(n)是节点n的估价函数,g(n)是在状态空间中从初始节点到n节点的实际代价,h(n)是从n节点到目标节点最佳路径的估计代价。
在这里主要是h(n)体现了搜索的启发信息,因为g(n)是已知的。
二、初识A*算法启发式搜索其实有很多的算法,比如:局部择优搜索法(如爬山法)、最好优先搜索法(Best-first)等等,当然A*也是。
这些算法都使用了启发函数,但在具体选取最佳搜索节点时,使用的策略不同。
比如局部择优搜索法,就是在搜索的过程中选取“最佳节点”后舍弃其他的兄弟节点、父节点,而一直搜索下去。
这种搜索的结果很明显,由于舍弃了其他的节点,可能也把最好的节点都舍弃了,因为求解的最佳节点只是在该阶段的最佳(局部的),并不一定是全局的最佳。
最好优先(Best-first)就聪明多了,他在搜索时,便没有舍弃节点(除非该节点是死节点),在每一步的估价中,把当前节点和以前节点的估价值作比较,得到一个“最佳的节点”。
这样可以有效的防止“最佳节点”的丢失。
那么A*算法又是一种什么样的算法呢?其实A*算法也是一种最好优先(Best-first)的算法。
只不过要加上一些约束条件罢了。
由于在一些问题求解时,我们希望能够求解出状态空间搜索的最短路径,也就是用最快的方法求解问题,A*就是干这种事情的!我们先下个定义,如果一个估价函数可以找出最短的路径,我们称之为可采纳性。
A*算法是一个可采纳的最好优先算法。
A*算法的估价函数可表示为:f'(n) = g'(n) + h'(n)这里,f'(n)是估价函数,g'(n)是起点到当前节点的最短路径值,h'(n)是n到目标的最短路经的启发值。
g'(n)的值实际上很容易从到目前为止的搜索树上计算出来,不必专门定义计算公式,也就是根据搜索历史情况对g'(n)作出计算,显然g(n)>=g'(n)。
h'(n)则依赖于启发信息,通常称为启发函数,是要对未来扩展的方向作出估计。
A*算法是按f'(n)递增的顺序来排列可能被扩展的节点,因而优先扩展f'(n)值最小的节点,体现了最好优先(Best-first)的搜索思想。
但有一点:h(n)<=h'(n)才可(这一点特别的重要)。
可以证明应用这样的估价函数是可以找到最短路径的,也就是可采纳的。
我们说应用这种估价函数的最好优先算法就是A*算法。
举一个例子,其实广度优先算法就是A*算法的特例。
其中g(n)是节点所在的层数,h(n)=0,这种h(n)肯定小于h'(n),所以由前述可知广度优先算法是一种可采纳的算法。
实际也是。
当然它是一种最臭的A*算法。
再说一个问题,就是有关h(n)启发函数的信息性。
h(n)的信息性通俗点说其实就是在估计一个节点的值时的约束条件,如果信息越多或约束条件越多则排除的节点就越多,估价函数越好或说这个算法越好。
这就是为什么广度优先算法的那么臭的原因了,谁叫它的h(n)=0,一点启发信息都没有。
但h(n)的信息越多,它的计算量就越大,耗费的时间就越多。
就应该适当的减小h(n)的信息,即减小约束条件。
但算法的准确性就差了,这里就有一个平衡的问题。
这是一个矛盾体,就看你怎样去掌握这个平衡了!下面举个例子说明h(n)的不同设计方法:1)将某一格局与目标格局比较,得到位置不符的数目;缺点:没有考虑数字移动的距离。
2)计算将数字移动到目的位置所需移动的距离之和;缺点:没有考虑牌排列的先后顺序,即若两个数字相邻,但与目的位置相比是相反的,则它们至少需要移动3次。
三.深入A*算法在这里我将对A*算法的实际应用进行一定的探讨,并且举一个有关A*算法在最短路径搜索的例子。
1、A*算法的程序编写原理在“初识A*算法”中说过,A*算法是最好优先算法的一种。
只是有一些约束条件而已。
我们先来看看最好优先算法是如何编写的吧。
如图有如下的状态空间:(起始位置是A,目标位置是P,字母后的数字表示节点的估价值)。
搜索过程中设置两个表:OPEN和CLOSED。
OPEN表保存了所有已生成而未考察的节点,CLOSED表中记录已访问过的节点。
算法中有一步是根据估价函数重排OPEN表的节点。
这样循环中的每一步只考虑OPEN表中状态最好的节点。
具体搜索过程如下:1)始状态:OPEN=[A5]; CLOSED=[];2)估算A5,取得所有子节点,并放入OPEN表中;OPEN=[B4, C4, D6]; CLOSED=[A5]3)估算B4,取得所有子节点,并放入OPEN表中;OPEN=[C4, E5, F5, D6]; CLOSED=[B4, A5]4)估算C4;取得所有子节点,并放入OPEN表中;OPEN=[H3, G4, E5, F5, D6]; CLOSED=[C4, B4, A5] 5)估算H3,取得所有子节点,并放入OPEN表中;OPEN=[O2, P3, G4, E5, F5, D6]; CLOSED=[H3, C4, B4, A5] 6)估算O2,取得所有子节点,并放入OPEN表中;OPEN=[P3, G4, E5, F5, D6]; CLOSED=[O2, H3, C4, B4, A5] 7)估算P3,已得到解。
算法结束看了具体的过程,再看看伪程序吧。
算法的伪程序如下:Best_First_Search(){Open = [起始节点];Closed = [];while ( Open表非空 ){从Open中取得一个节点X, 并从OPEN表中删除.if (X是目标节点){求得路径PATH;返回路径PATH;}for (每一个X的子节点Y){if( Y不在OPEN表和CLOSED表中 ){求Y的估价值;并将Y插入OPEN表中; //还没有排序}else if( Y在OPEN表中 ){if( Y的估价值小于OPEN表的估价值 )更新OPEN表中的估价值;}else //Y在CLOSED表中{if( Y的估价值小于CLOSED表的估价值 ){更新CLOSED表中的估价值;从CLOSED表中移出节点, 并放入OPEN表中;}}将X节点插入CLOSED表中;按照估价值将OPEN表中的节点排序;} //end for} //end while} //end func伪程序出来了,写一个源程序应该不是问题了,依葫芦画瓢就可以。
A*算法的程序与此是一样的,只要注意估价函数中的g(n)的h(n)约束条件就可以了。
下面,我们可以进入另一个重要的话题,用A*算法实现最短路径的搜索。
在此之前你最好认真的理解前面的算法。
2、用A*算法实现最短路径的搜索在实际应用中中,经常要涉及到最短路径的搜索,现在一个比较好的方法就是用A*算法进行设计。
先复习一下,A*算法的核心是估价函数f(n),它包括g(n)和h(n)两部分。
g(n)是已经走过的代价,h(n)是n到目标的估计代价。
在这个例子中g(n)表示在状态空间从起始节点到n节点的深度,h(n)表示n节点所在地图的位置到目标位置的直线距离。
一个是状态空间,一个是实际的地图,不要搞错了。
再详细点说,有一个物体A,在地图上的坐标是(xa,ya),A所要到达的目标b的坐标是(xb,yb)。
则开始搜索时,设置一个起始节点1,生成八个子节点2 - 9 因为有八个方向。
如图:先看搜索主函数:void AstarPathfinder::FindPath(int sx, int sy, int dx, int dy){NODE *Node, *BestNode;int TileNumDest;//得到目标位置,作判断用TileNumDest = TileNum(sx, sy);//生成Open和Closed表OPEN=( NODE* )calloc(1,sizeof( NODE ));CLOSED=( NODE* )calloc(1,sizeof( NODE ));//生成起始节点,并放入Open表中Node=( NODE* )calloc(1,sizeof( NODE ));Node->g = 0;//这是计算h值Node->h = (dx-sx)*(dx-sx) + (dy-sy)*(dy-sy); // should really use sqrt().//这是计算f值,即估价值Node->f = Node->g+Node->h;Node->NodeNum = TileNum(dx, dy);Node->x = dx;Node->y = dy;OPEN->NextNode=Node; // make Open List point to first nodefor (;;){//从Open表中取得一个估价值最好的节点BestNode=ReturnBestNode();//如果该节点是目标节点就退出if (BestNode->NodeNum == TileNumDest) // if we've found the end, break and finish break;//否则生成子节点GenerateSuccessors(BestNode,sx,sy);}PATH = BestNode;}再看看生成子节点函数 GenerateSuccessors:void AstarPathfinder::GenerateSuccessors(NODE *BestNode, int dx, int dy){int x, y;//依次生成八个方向的子节点// Upper-Leftif ( FreeTile(x=BestNode->x-TILESIZE, y=BestNode->y-TILESIZE) )GenerateSucc(BestNode,x,y,dx,dy);// Upperif ( FreeTile(x=BestNode->x, y=BestNode->y-TILESIZE) )GenerateSucc(BestNode,x,y,dx,dy);// Upper-Rightif ( FreeTile(x=BestNode->x+TILESIZE, y=BestNode->y-TILESIZE) )GenerateSucc(BestNode,x,y,dx,dy);// Rightif ( FreeTile(x=BestNode->x+TILESIZE, y=BestNode->y) )GenerateSucc(BestNode,x,y,dx,dy);// Lower-Rightif ( FreeTile(x=BestNode->x+TILESIZE, y=BestNode->y+TILESIZE) )GenerateSucc(BestNode,x,y,dx,dy);// Lowerif ( FreeTile(x=BestNode->x, y=BestNode->y+TILESIZE) )GenerateSucc(BestNode,x,y,dx,dy);// Lower-Leftif ( FreeTile(x=BestNode->x-TILESIZE, y=BestNode->y+TILESIZE) )GenerateSucc(BestNode,x,y,dx,dy);// Leftif ( FreeTile(x=BestNode->x-TILESIZE, y=BestNode->y) )GenerateSucc(BestNode,x,y,dx,dy);}看看最重要的函数GenerateSucc:void AstarPathfinder::GenerateSucc(NODE *BestNode,int x, int y, int dx, int dy){int g, TileNumS, c = 0;NODE *Old, *Successor;//计算子节点的 g 值g = BestNode->g+1; // g(Successor)=g(BestNode)+cost of getting from BestNode to SuccessorTileNumS = TileNum(x,y); // identification purposes//子节点再Open表中吗?if ( (Old=CheckOPEN(TileNumS)) != NULL ) // if equal to NULL then not in OPEN list,// else it returns the Node in Old{//若在for( c = 0; c <8; c++)if( BestNode->Child[c] == NULL ) // Add Old to the list of BestNode's Children// (or Successors).break;BestNode->Child[c] = Old;//比较Open表中的估价值和当前的估价值(只要比较g值就可以了)if ( g g ) // if our new g value is Parent = BestNode;Old->g = g;Old->f = g + Old->h;}}else //在Closed表中吗?if ( (Old=CheckCLOSED(TileNumS)) != NULL ) // if equal to NULL then not in OPEN list// else it returns the Node in Old{//若在for( c = 0; c<8; c++)if ( BestNode->Child[c] == NULL ) // Add Old to the list of BestNode's// Children (or Successors).break;BestNode->Child[c] = Old;//比较Closed表中的估价值和当前的估价值(只要比较g值就可以了)if ( g g ) // if our new g value is Parent = BestNode;Old->g = g;Old->f = g + Old->h; //再依次更新Old的所有子节点的估价值PropagateDown(Old); // Since we changed the g value of Old, we need// to propagate this new value downwards, i.e.// do a Depth-First traversal of the tree!}}else //不在Open表中也不在Close表中{//生成新的节点Successor = ( NODE* )calloc(1,sizeof( NODE ));Successor->Parent = BestNode;Successor->g = g;Successor->h = (x-dx)*(x-dx) + (y-dy)*(y-dy); // should do sqrt(), but since we// don't reallySuccessor->f = g+Successor->h; // care about the distance but just which branchlooks Successor->x = x; // better this should suffice. Anyayz it's faster.Successor->y = y;Successor->NodeNum = TileNumS;//再插入Open表中,同时排序。