簡體   English   中英

Dijkstra的算法不起作用

[英]Dijkstra's algorithm not working

我正在為學校項目創建游戲,我想將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是起始節點。

有人知道我在做什么錯嗎?

在Dijkstra算法中,僅將最短擴充路徑指向的節點標記為已訪問。 我可以看到您在這里犯的錯誤:

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

不要將節點標記為立即訪問。

標記為只訪問了節點u將指向循環后

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

否則,對於每一項改進,您都將節點標記為已訪問,甚至不處理所有節點。

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

要實現Dijkstra算法,您需要維護兩個節點列表:

  • 搜索到的節點列表
  • 邊緣節點的排序列表。
    此列表中的每個節點都有到達此位置的成本。

我在您的代碼中都看不到這些列表。

您還將成本存儲在節點中。 這將不起作用,因為到達節點的成本將取決於路由(除非您可以存儲與節點關聯的多個成本)。

我希望代碼看起來像這樣:

 // 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);
          }
     }
 }

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM