Dijkstra的算法不起作用

时间:2013-01-03 09:21:40

标签: c++ algorithm dijkstra

我正在为学校项目创建一个游戏,我想将Dijkstra的算法用作AI的一部分,用于玩家需要躲避的物体。

所以我有一个图形(一个邻接矩阵),我想使用Dijkstra来获取从每个对象到玩家的路径,但是现在当我调用算法时,如果玩家跟在后面,它将找不到玩家对象。

根据我的理解,Dijkstra的算法应该访问所有节点,直到它找到目的地,但在我的情况下它不是。

这是我的算法到目前为止的样子:

Node* Graph::DijkstrasAlgorithm(Node* sNode, Node* dNode){
    std::cout<<"Hello Dijkstra!!"<<std::endl;
    for(unsigned int i = 0; i < this->nodeList.size(); ++i){
        nodeList.at(i)->setDistance(INT_MAX);
        nodeList.at(i)->setVisited(false);
    }
    std::cout<<"everything is set"<<std::endl;
    sNode->setDistance(0);
    int numberVisited = 0;
    Node* u = new Node();
    std::cout<<"before while lus"<<std::endl;
    while(numberVisited < numberOfNodes){
        u->setDistance(INT_MAX);
        for(unsigned int j = 0; j < this->nodeList.size(); ++j){
            if((u->getDistance() > this->nodeList.at(j)->getDistance()) && !this->nodeList.at(j)->isVisited() ){
                u = this->nodeList.at(j);
                u->setVisited(true);
                numberVisited++;
            }
        }

    std::cout<<u->getNodeName()<<"=="<<dNode->getNodeName()<<std::endl;
        if((u == dNode) || (u->getDistance() == INT_MAX)){
            std::cout<<"true"<<std::endl;
            break;
        }


        for(int k = 0; k < u->numberOfneighbors(); ++k){
            if(!u->getNeighbors(k)->isVisited())
            {
            //  std::cout<<u->getDistance()<<std::endl;
                int alt = u->getDistance() + 1;
                if( alt < u->getNeighbors(k)->getDistance()){
                     u->getNeighbors(k)->setDistance(alt);
                     u->getNeighbors(k)->setPrevious(u);
                }
            }
        }

    }
    std::vector<Node* > stack;
    u = dNode;
    while(u->getPrevious() != NULL){
        stack.insert(stack.begin(), u);
        u = u->getPrevious();
    }
    if(!stack.empty())
        return stack.at(0);
    else
        return sNode;


}

在这种情况下,dNode是目标节点,sNode是起始节点。

有谁知道我做错了什么?

2 个答案:

答案 0 :(得分:3)

在Dijkstra算法中,您将标记为仅访问最短扩充路径所指向的节点。我可以看到你在这里犯的错误:

u = this->nodeList.at(j);
u->setVisited(true);

不要立即将节点标记为已访问。

标记为仅访问节点u将指向循环

之后
for(unsigned int j = 0; j < this->nodeList.size(); ++j){

否则,对于每次改进,您都会将节点标记为已访问,甚至不会处理所有节点。

答案 1 :(得分:1)

它甚至看起来都不像Dijkstra算法。

要实现Dijkstra算法,您需要维护两个节点列表:

  • 搜索节点列表
  • 边缘节点的SORTED列表 此列表中的每个节点都有到达此位置的费用。

我在你的代码中看不到这些列表。

您还要在节点中存储费用。这不起作用,因为到达节点的成本将取决于路由(除非您可以存储与节点关联的多个成本)。

我希望代码看起来像这样:

 // pseudo code.
 // Note all features used are strictly available
 //
 Node* Graph::DijkstrasAlgorithm(Node* sNode, Node* dNode)
 {
     std::list<Node*>                    searchedNodes;
     std::list<std::pair<Node*, cost>>   edgeNodes;

     edgeNodes.push_sorted(sNode, 0);

     while(!edgeNodes.empty())
     {
          std::pair<Node*, cost>  next = edgeNodes.pop_front();
          searchedNodes.push_back(next.first);

          if (next.first == dnode)
          {   // We found the route
              return STUFF;
          }

          for(Edge* edge, next.first->getEdges())
          {
              if (searchedNodes.find(edge->dst) != searchedNodes.end())
              {   continue;
              }

              edgeNodes.push_sorted(dest.dst, next.second + edge->cost);
          }
     }
 }