Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/129.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ A*保证找到最短路径的寻路?_C++_Artificial Intelligence_Path Finding - Fatal编程技术网

C++ A*保证找到最短路径的寻路?

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

如果正确实施,A*路径查找算法是否保证100%或100%的时间找到最短路径

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