关于A*寻路算法的认识
2015-04-20 23:58
134 查看
最近要参加学校的APP比赛,我们组做的是一个3D迷宫的小APP,我负责的是迷宫的生成与寻路。
寻路算法选择的是A*寻路算法,具体参考的是下面的这篇博客。
本文主要是谈谈自己对A*算法的理解,具体细节,上文链接以及讲的很详细了。
/article/4844143.html
关于A*算法的实现我是用的广度优先搜索这种比较常见的实现模式。
那么关于这两者之间的关系是怎么样呢?
个人理解的是A*算法其实是一种带有路径信息的有策略的广度优先搜索,我们平常用的广度优先搜索,没有带有路径信息,搜索起来是一种盲目的搜索。
例如,当寻路到A节点时,下一步是以A为中心,分别测试A周围的8个点,并且又以它们为中心,继续向外扩散,以期找到待寻找的点。
这样的搜索带有盲目性,测试了大量的无效的点。
A*算法在每个节点中加入了路径的信息:
F:当前点的路径信息,包含了到当前点到起点与到终点的信息。(F=G+H)
G:当前点到唯一的起点的路径信息。
H:当前点到指定终点的距离信息。
那么我们怎么样通过这些指定的路径信息来避免广度优先搜索的盲目选取下一个路径点而得到一条最小路径呢?
其实我们可以把这看成是一个最小路径的“感染”问题。
F B C D
E A G H
I N K L
如上图:
首先参照上文博客,水平方向移动一格路径代价是10,斜方向移动一格路径代价是14。
起点A的G值初始化0,这个当然,自己到自己的距离是0;其它点中的G初始化为INT_MAX;通过对A的广度搜索,来设置各个节点的G值与父节点。
例:A的八个方向,FBCEGINK,选取出F最小的点,假设为G。
对G的八个方向,BCDAHNKL,我们同样需要设定这8个方向的G值与父节点。这8个方向中与A重叠的有BCNK。
重叠意味着有两条路径,对于K来说,可以是A->K,也可以是A->G->K。
那么怎么样选择呢?
这时我们要判断G的值,哪条路径使得G的值最小,我们就选择它。
G的值是起点A到本节点的路径长度,这是一个累积的值,是前面各个G一路累积(感染)下来的,代表的是当前的路径,我们选择的肯定是使得K的G最小,这样对整个最小路径都是有利的,因为可以一直感染下去。
那么H的作用在哪里呢?
H仅仅是对路径方向的一个大致的判断,上图中,若指定终点在A的右边,那么EFI肯定不会被选中,这样就不用盲目的8个方向都去判断。
终上所述:
G和H的作用共同体现于F中,每次我们都是在广度搜索中去寻找F最小的点,然后根据G的值,设置下一个广度搜索中的节点的父节点,父节点永远是使得子节点中的G值最小。(到起点A的路径最短)。
自己写的A*的核心函数代码,测试curr节点的周围8个节点,并且设置路径及父节点信息,其余的部分则是广度优先搜索的框架,这里不再写出来。
寻路算法选择的是A*寻路算法,具体参考的是下面的这篇博客。
本文主要是谈谈自己对A*算法的理解,具体细节,上文链接以及讲的很详细了。
/article/4844143.html
关于A*算法的实现我是用的广度优先搜索这种比较常见的实现模式。
那么关于这两者之间的关系是怎么样呢?
个人理解的是A*算法其实是一种带有路径信息的有策略的广度优先搜索,我们平常用的广度优先搜索,没有带有路径信息,搜索起来是一种盲目的搜索。
例如,当寻路到A节点时,下一步是以A为中心,分别测试A周围的8个点,并且又以它们为中心,继续向外扩散,以期找到待寻找的点。
这样的搜索带有盲目性,测试了大量的无效的点。
A*算法在每个节点中加入了路径的信息:
F:当前点的路径信息,包含了到当前点到起点与到终点的信息。(F=G+H)
G:当前点到唯一的起点的路径信息。
H:当前点到指定终点的距离信息。
那么我们怎么样通过这些指定的路径信息来避免广度优先搜索的盲目选取下一个路径点而得到一条最小路径呢?
其实我们可以把这看成是一个最小路径的“感染”问题。
F B C D
E A G H
I N K L
如上图:
首先参照上文博客,水平方向移动一格路径代价是10,斜方向移动一格路径代价是14。
起点A的G值初始化0,这个当然,自己到自己的距离是0;其它点中的G初始化为INT_MAX;通过对A的广度搜索,来设置各个节点的G值与父节点。
例:A的八个方向,FBCEGINK,选取出F最小的点,假设为G。
对G的八个方向,BCDAHNKL,我们同样需要设定这8个方向的G值与父节点。这8个方向中与A重叠的有BCNK。
重叠意味着有两条路径,对于K来说,可以是A->K,也可以是A->G->K。
那么怎么样选择呢?
这时我们要判断G的值,哪条路径使得G的值最小,我们就选择它。
G的值是起点A到本节点的路径长度,这是一个累积的值,是前面各个G一路累积(感染)下来的,代表的是当前的路径,我们选择的肯定是使得K的G最小,这样对整个最小路径都是有利的,因为可以一直感染下去。
那么H的作用在哪里呢?
H仅仅是对路径方向的一个大致的判断,上图中,若指定终点在A的右边,那么EFI肯定不会被选中,这样就不用盲目的8个方向都去判断。
终上所述:
G和H的作用共同体现于F中,每次我们都是在广度搜索中去寻找F最小的点,然后根据G的值,设置下一个广度搜索中的节点的父节点,父节点永远是使得子节点中的G值最小。(到起点A的路径最短)。
自己写的A*的核心函数代码,测试curr节点的周围8个节点,并且设置路径及父节点信息,其余的部分则是广度优先搜索的框架,这里不再写出来。
void getSurrroundPoints(point& curr, list<point>& result) { int x = curr.m_x; //curr坐标信息 int y = curr.m_y; for (int i = x-1;i <= x+1; i++) { for (int j = y - 1; j <= y + 1; j++) //8个方向 { if (i == x && j == y) //循环到自己,跳过此次循环 continue; if ( find_if(closeList.begin(), closeList.end(), pointEqualLocation(i, j)) == closeList.end() //当前节点还没有被检查过 &&canReach(i, j)) //当前节点不是障碍物 { if (x == i || y == j) //上下左右四个方向 g=10 { if ((curr.m_g + 10) >= point_ptr[i][j].m_g) { //start到(i,j)的 不必经过curr //什么也不做,保留原来的路径信息与父节点 } else { //start到(i,j)的 经过curr路径会更小 //更新路径信息 更改父节点 point_ptr[i][j].m_g = curr.m_g + 10; //更新节点中的G值 point_ptr[i][j].m_fx = curr.m_x; //设置父节点 point_ptr[i][j].m_fy = curr.m_y; } } else //斜方向 g=14; { if ((curr.m_g + 14) >= point_ptr[i][j].m_g) { //start到(i,j)的 不必经过curr //什么也不做,保留原来的路径信息与父节点 } else { //start到(i,j)的 经过curr路径会更小 //更新路径信息 更改父节点 point_ptr[i][j].m_g = curr.m_g + 14; //更新节点中的G值 point_ptr[i][j].m_fx = curr.m_x; //设置父节点 point_ptr[i][j].m_fy = curr.m_y; } } point_ptr[i][j].m_h = abs(endPoint_x - i) + abs(endPoint_y - j); //计算到终点的距离 point_ptr[i][j].m_f = point_ptr[i][j].m_g + point_ptr[i][j].m_h; //F=G+H result.push_back(point_ptr[i][j]); //放到链表中 等待下次的检查 } } } }
相关文章推荐
- 关于在标准库算法中使用函数对象的一点认识
- 关于寻路算法的一些思考(11):寻路算法的其他应用
- 关于智能寻路算法的研究,A-Star算法拓展,B星寻路算法
- 关于A*寻路算法的实现
- 关于游戏开发中的A*/A-star的寻路算法的问题
- 关于帝国2中的寻路和行军算法
- 关于帝国2中的寻路和行军算法
- 关于Java权限控制算法
- 关于C语言指针的一些新认识(1)
- 关于图像快速缩放算法,目前看到的最好的最清晰的一篇文章
- 理解A*寻路算法具体过程
- 关于算法的一些资料
- 在j2me中A*寻路算法的简化
- 关于伙伴算法
- 关于sort算法的总结
- A*寻路算法入门(六)
- 关于《海量用户积分算法探讨》的读后总结和扩展
- 关于寻路算法的一些思考(1):A*算法介绍
- 《Delphi 算法与数据结构》学习与感悟[4]: 关于 const
- 关于中断的一点点认识