A* 寻路算法保证找到最短路径吗?

如果 A* 寻路算法实现正确,它是否能 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;}

回答:

是的(但我没有深入研究你的实现)。

大多数人忽略的一点是,启发式算法必须低估到达最终解决方案的遍历成本(这被称为“可采纳性”)。 启发式算法单调地接近解决方案也很好(但不是绝对必需的)(这被称为“一致性”)。


无论如何,粗略地看了一下你的代码,你可能应该使用std::set作为你的 closed list,使用 std::deque 作为你的 open list,这样你在这两个列表中的搜索和插入就不会是 O(n)。 你也不应该 new NodeRecords,因为它给你带来了一个间接级别,没有任何好处(如果抛出异常,你的算法会泄漏内存)。

Related Posts

L1-L2正则化的不同系数

我想对网络的权重同时应用L1和L2正则化。然而,我找不…

使用scikit-learn的无监督方法将列表分类成不同组别,有没有办法?

我有一系列实例,每个实例都有一份列表,代表它所遵循的不…

f1_score metric in lightgbm

我想使用自定义指标f1_score来训练一个lgb模型…

通过相关系数矩阵进行特征选择

我在测试不同的算法时,如逻辑回归、高斯朴素贝叶斯、随机…

可以将机器学习库用于流式输入和输出吗?

已关闭。此问题需要更加聚焦。目前不接受回答。 想要改进…

在TensorFlow中,queue.dequeue_up_to()方法的用途是什么?

我对这个方法感到非常困惑,特别是当我发现这个令人费解的…

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注