赞
踩
A*算法最初发表于1968年,由Stanford研究院的Peter Hart, Nils Nilsson以及Bertram Raphael发表。它可以被认为是Dijkstra算法的扩展。
由于借助启发函数的引导,A*算法通常拥有更好的性能。
A*吸取了Dijkstra 算法中的cost_so_far,为每个边长设置权值,不停的计算每个顶点到起始顶点的距离(G),以获得最短路线,
同时也汲取贪婪最佳优先搜索算法中不断向目标前进优势,并持续计算每个顶点到目标顶点的距离(Heuristic distance),以引导搜索队列不断想目标逼近,从而搜索更少的顶点,保持寻路的高效。
启发函数会影响A*算法的行为。
由上面这些信息我们可以知道,通过调节启发函数我们可以控制算法的速度和精确度。因为在一些情况,我们可能未必需要最短路径,而是希望能够尽快找到一个路径即可。这也是A*算法比较灵活的地方。
对于网格形式的图,有以下这些启发函数可以使用:
- 把起始格添加到 "开启列表"
- do
- {
- 寻找开启列表中F值最低的格子, 我们称它为当前格.
- 把它切换到关闭列表.
- 对当前格相邻的8格中的每一个
- if (它不可通过 || 已经在 "关闭列表" 中)
- {
- 什么也不做.
- }
- if (它不在开启列表中)
- {
- 把它添加进 "开启列表", 把当前格作为这一格的父节点, 计算这一格的 FGH
- }
- if (它已经在开启列表中)
- {
- if (用 G 值为参考检查新的路径是否更好, 更低的G值意味着更好的路径)
- {
- 把这一格的父节点改成当前格, 并且重新计算这一格的 GF 值.
- }
- }
- } while( 目标格已经在 "开启列表", 这时候路径被找到)
- 如果开启列表已经空了, 说明路径不存在.
-
- 最后从目标格开始, 沿着每一格的父节点移动直到回到起始格, 这就是路径.

主循化
- void Astar(const int x, const int y)
- {
- if(x == y)
- {
- plan_path.clear();
- plan_path.push_back(x);
- isfindpath = true;
- std::cout << "---------------------------------------------------" << std::endl;
- std::cout << "* find! *" << std::endl;
- return;
- }
-
- openlist.clear();
- closelist.clear();
- //放入起点
- openlist.push_back(x);
- plan_ways_map[x]->G = 0;
- plan_ways_map[x]->H = Calculateh(y, x);
- plan_ways_map[x]->F = Calculatef(x);
- while (!openlist.empty())
- {
- int minidnode = Findleastf(openlist);//找到F值最小的点
-
- openlist.remove(minidnode);//从开启列表中删除
- closelist.push_back(minidnode);//放到关闭列表
-
- //1,找到下一步待选点
- std::vector<int> candiates = Getnextnode(minidnode);
- for(int i = 0; i < candiates.size(); ++i)
- {
- //2,对某一点,如果它不在开启列表中,加入到开启列表,设置当前格为其父节点,计算F G H
- if(!Isinlist(candiates[i], openlist))
- {
- plan_ways_map[candiates[i]]->parent = minidnode;
- plan_ways_map[candiates[i]]->G = Calculateg(x, candiates[i]);
- plan_ways_map[candiates[i]]->H = Calculateh(y, candiates[i]);
- plan_ways_map[candiates[i]]->F = Calculatef(candiates[i]);
- openlist.push_back(candiates[i]);
- }else{
- //3,对某一点,它在开启列表中,计算G值, 如果比原来的大, 就什么都不做, 否则设置它的父节点为当前点,并更新G和F
- double tempg = Calculateg(x, candiates[i]);
- if(tempg > plan_ways_map[candiates[i]]->G)
- {
- continue;
- }else{
- plan_ways_map[candiates[i]]->parent = minidnode;
- plan_ways_map[candiates[i]]->G = tempg;
- plan_ways_map[candiates[i]]->F = Calculatef(candiates[i]);
- }
- }
- //如果结束点出现在openlist则搜索成功
- if(Isinlist(y, openlist))
- {
- plan_ways_map[y]->parent = minidnode;
- std::cout << "---------------------------------------------------" << std::endl;
- std::cout << "* find! *" << std::endl;
- int i = y;
- while(i != -1)
- {
- plan_path.push_back(i);
- i = plan_ways_map[i]->parent;
- }
- std::reverse(plan_path.begin(), plan_path.end());
- isfindpath = true;
- return;
- }
- }
- }
- std::cout << "---------------------------------------------------" << std::endl;
- std::cout << "* not find! *" << std::endl;
- return;
- }

其他函数
- //计算起点到当前点的代价
- double Calculateg(const int x, const int idg) const
- {
-
- }
-
- //估计当前点到终点的代价
- double Calculateh(const int y, const int idh) const
- {
-
- }
-
- //计算总代价,预置A*接口,Dijkstra相当于简化版A*
- double Calculatef(const int idf) const
- {
-
- }
-
- //从list中找出总代价的点
- int Findleastf(const std::list<int> &listx) const
- {
-
- }
-
- //从当前索引idx找到可行的下一点集合
- std::vector<int> Getnextnode(const int idx) const
- {
-
- }
-
- //判断x点是否在list中
- bool Isinlist(const int x, const std::list<int> &listx) const
- {
-
- }

Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。