C++ A*保证找到最短路径的寻路?
如果正确实施,A*路径查找算法是否保证100%或100%的时间找到最短路径C++ A*保证找到最短路径的寻路?,c++,artificial-intelligence,path-finding,C++,Artificial Intelligence,Path Finding,如果正确实施,A*路径查找算法是否保证100%或100%的时间找到最短路径 int Graph::FindPath(Node *start, Node *finish, list< vec2f > &path) { list<NodeRecord*> open; list<NodeRecord*> closed; list<NodeRecord*>::iterator openIt; list<Node
int Graph::FindPath(Node *start, Node *finish, list< vec2f > &path)
{
list<NodeRecord*> open;
list<NodeRecord*> closed;
list<NodeRecord*>::iterator openIt;
list<NodeRecord*>::iterator closedIt;
// add the starting node to the open list
open.push_back( new NodeRecord(start, NULL, 0.0f, 0.0f + start->pos.DistanceSq(finish->pos) ) );
// NodeRecord(Node *node, Node *from, float cost, float totalCost)
while(!open.empty())
{
// find the node record with the lowest cost
NodeRecord *currentRecord = open.front();
openIt = ++open.begin();
while(openIt != open.end())
{
if((*openIt)->total < currentRecord->total)
currentRecord = (*openIt);
openIt++;
}
// get a pointer to the current node
Node *currentNode = currentRecord->node;
// if the current node is the finish point
if(currentNode == finish)
{
// add the finish node
path.push_front(currentNode->pos);
// add all the from nodes
Node *from = currentRecord->from;
while(!closed.empty())
{
// if this node record is where the path came from,
if(closed.back()->node == from) //&& closed.back()->from != NULL
{
// add it to the path
path.push_front( from->pos );
// get the next 'from' node
from = closed.back()->from;
}
// delete the node record
delete closed.back();
closed.pop_back();
}
while(! open.empty() )
{
delete open.back();
open.pop_back();
}
// a path was found
return 0;
}
// cycle through all neighbours of the current node
bool isClosed, isOpen;
for(int i = 0; i < (int)currentNode->neighbours.size(); i++)
{
// check if neigbour is on the closed list
isClosed = false;
closedIt = closed.begin();
while(closedIt != closed.end())
{
if(currentNode->neighbours[i] == (*closedIt)->node)
{
isClosed = true;
break;
}
closedIt++;
}
// skip if already on the closed list
if(isClosed == true)
continue;
float cost = currentRecord->cost + currentNode->distance[i];
float totalCost = cost + currentNode->neighbours[i]->pos.DistanceSq(finish->pos);
// check if this neighbour is already on the open list
isOpen = false;
openIt = open.begin();
while(openIt != open.end())
{
if(currentNode->neighbours[i] == (*openIt)->node)
{
// node was found on the open list
if(totalCost < (*openIt)->total)
{
// node on open list was updated
(*openIt)->cost = cost;
(*openIt)->total = totalCost;
(*openIt)->from = currentNode;
}
isOpen = true;
break;
}
openIt++;
}
// skip if already on the open list
if(isOpen == true)
continue;
// add to the open list
open.push_back( new NodeRecord(currentNode->neighbours[i], currentNode, cost, totalCost) );
}
// move the current node to the closed list after it has been evaluated
closed.push_back( currentRecord );
open.remove( currentRecord );
}
// free any nodes left on the closed list
while(! closed.empty() )
{
delete closed.back();
closed.pop_back();
}
// no path was found
return -1;
}
int-Graph::FindPath(节点*开始,节点*完成,列表&path)
{
列表打开;
名单已关闭;
列表::迭代器openIt;
列表::迭代器closedIt;
//将起始节点添加到打开列表中
打开。推回(新节点记录(开始、空、0.0f、0.0f+开始->位置距离SQ(完成->位置));
//节点记录(节点*节点,节点*发件人,浮动成本,浮动总成本)
而(!open.empty())
{
//查找成本最低的节点记录
NodeRecord*currentRecord=open.front();
openIt=++open.begin();
while(openIt!=open.end())
{
如果((*openIt)->totaltotal)
currentRecord=(*打开它);
openIt++;
}
//获取指向当前节点的指针
节点*currentNode=currentRecord->Node;
//如果当前节点是终点
如果(currentNode==finish)
{
//添加finish节点
路径向前推(当前节点->位置);
//添加所有来自节点的
节点*from=currentRecord->from;
而(!closed.empty())
{
//如果此节点记录是路径的来源,
if(closed.back()->node==from)/&&closed.back()->from!=NULL
{
//将其添加到路径中
路径。向前推(从->位置);
//获取下一个“来自”节点
from=closed.back()->from;
}
//删除节点记录
删除closed.back();
关闭。向后弹出();
}
而(!open.empty())
{
删除open.back();
open.pop_back();
}
//找到了一条路
返回0;
}
//循环遍历当前节点的所有邻居
bool是封闭的,isOpen;
对于(int i=0;i<(int)currentNode->neights.size();i++)
{
//检查neigbour是否在关闭列表中
isClosed=false;
closedIt=closed.begin();
while(closedIt!=closed.end())
{
如果(currentNode->Neights[i]=(*closedIt)->node)
{
isClosed=true;
打破
}
closedIt++;
}
//如果已在关闭列表中,则跳过
如果(isClosed==true)
继续;
浮动成本=当前记录->成本+当前节点->距离[i];
float totalCost=成本+currentNode->neurs[i]>pos.DistanceSq(finish->pos);
//检查此邻居是否已在开放列表中
isOpen=假;
openIt=open.begin();
while(openIt!=open.end())
{
如果(currentNode->Neights[i]==(*openIt)->node)
{
//在打开的列表中找到节点
如果(总成本<(*openIt)->总成本)
{
//已更新打开列表上的节点
(*openIt)->成本=成本;
(*openIt)->总计=总成本;
(*openIt)->from=currentNode;
}
isOpen=真;
打破
}
openIt++;
}
//如果已在打开列表中,则跳过
如果(等参==真)
继续;
//添加到打开的列表中
打开。推回(新节点记录(当前节点->邻居[i],当前节点,成本,总成本));
}
//计算完当前节点后,将其移动到关闭列表中
关闭。推回(当前记录);
打开。删除(当前记录);
}
//释放关闭列表中剩余的所有节点
而(!closed.empty())
{
删除closed.back();
关闭。向后弹出();
}
//找不到路径
返回-1;
}
(但我还没有深入研究您的实现)
大多数人忽略的一点是,启发式算法必须低估遍历最终解决方案的成本(称为“”)。启发式方法单调地接近解决方案也是很好的(但不是绝对必需的)(这称为“”)
无论如何,我看了一下您的代码,您可能应该对关闭的列表使用
std::set
,对打开的列表使用std::deque
,这样您在这两个列表中的搜索和插入就不会是O(n)。你也不应该制作新的节点记录,因为它给了你一个间接的层次,没有任何好处(如果抛出异常,你的算法会泄漏内存)。根据,a*使用启发式来更快地找到最短路径,但实际上它是对Dijkstra最短路径算法的修改,如果启发法不够好,A*的作用实际上与Dijkstra相同
因此,是的,保证A*找到最短路径。有趣的是,虽然可接受的启发式算法在100%的时间内提供最佳解决方案,但在某些情况下它们可能会很慢。如果有多条路径的总距离大致相同,则不可接受的启发式将在相对等效的路径之间提供更快的“决策”。请注意,您必须使用一个封闭列表(您这样做了)才能使其工作 事实上,Pearl在他的书《启发法》中证明,如果你的启发法高估了一小部分,那么所提供的解决方案只会比最优解长相同数量(最多)
对于某些快速/实时应用程序,这对提高速度非常有帮助,但对解决方案质量的影响很小。只要启发式是可接受的。@Trav