使用BFS解决3D迷宫如果在C ++中找到了,如何获得到终点的最短路径?

问题描述

我正在尝试实施BFS算法,以检查在指定起始位置的3D迷宫中是否可以达到目标。迷宫是从txt文件导入的。我的解决方案似乎找到了目标,但是我无法仅显示所采取的路径。我的问题:我能够找到目标,但是我不知道如何获得最短的路径并将其打印出来。我当时正在考虑使用父母/子女概念,但不确定是否可行。 我希望我最终可以打印出这样的路径:(从起点到终点)

1 3 1
1 3 2
2 3 3

这是我的代码

我使用struct来存储txt文件中的信息。

struct Maze
{
    int x,y,z; //dimensions
    int sx,sy,sz;//start point
    int ex,ey,ez;//exit point
    int grids; //number of grids in the maze where are actions available
    vector<vector<int> > glist;
    vector< pair<int,pair<int,int> > > gpoint; // list of (x,z) accessible
};
void BFS(Maze &maze,vector< pair<int,int> > > result){
    bool reach_end = false;
    int xx,yy,zz;                               
    int j=0;
    int move_count = 0;
    int nodes_left_in_layer = 1;
    int nodes_in_next_layer = 0;
    queue<int> xq,yq,zq;
    xq.push(maze.sx);yq.push(maze.sy);zq.push(maze.sz);
    

    vector< pair<int,int> > > visited(maze.grids);
    visited.push_back(make_pair(xx,make_pair(yy,zz)));
    result.push_back(make_pair(xx,zz)));

    while(!xq.empty()){
        int xfront = xq.front();int yfront = yq.front();int zfront = zq.front();
        xq.pop();yq.pop();zq.pop();
        
        if(xfront==maze.ex && yfront==maze.ey && zfront==maze.ez){
            reach_end = true;
            cout << "reach end!" <<endl;
            break;
        }
        int index=0;
        index = getindex(maze,xfront,yfront,zfront);
    
        
        //EXPLORE NEIGHBORS
        for(j=0;j<maze.glist[index].size()-3;j++){
        
            int action = maze.glist[index][3+j];
            
            xx = xfront+dx[action-1];    // dx,dy,dz are lists of actions. 
            yy = yfront+dy[action-1];
            zz = zfront+dz[action-1];
            auto p2 = make_pair(xx,zz));
        
            //skip bounds
            if(xx<0 || yy<0 || zz<0){}
            else if(xx >= maze.x || yy>= maze.y || zz >= maze.z){}
            else if(find(visited.begin(),visited.end(),p2)!=visited.end()){
                cout << "Visited: "<<xx <<yy<<zz<<endl;
            }
            else if(find(maze.gpoint.begin(),maze.gpoint.end(),p2)!=maze.gpoint.end()){
            
                int index2 = getindex(maze,xx,zz);
                xq.push(xx);yq.push(yy);zq.push(zz);
                visited.push_back(p2);
                nodes_in_next_layer++;
            }else{
                cout<<"Not in glist!! "<<endl;
            }
        
        }
  
        nodes_left_in_layer--;
        if(nodes_left_in_layer==0){
            nodes_left_in_layer = nodes_in_next_layer;
            nodes_in_next_layer=0;
            move_count++;
        }
    
    
    }
    if(reach_end){
    
        cout<< "move_count: " <<move_count<<endl;
        cout << "nodes_left_in_layer: " <<nodes_left_in_layer<<endl;
        cout << "nodes_in_next_layer: " <<nodes_in_next_layer<<endl;
    }else{
        cout<< "xxxFAILxxx " <<endl;
    }
}

解决方法

有2种常见方式:

  1. 您会记住每个访问的像元从起点开始的距离,然后当您找到终点时,您将沿着沿着每步减小距离的路径回到起点。当您可以对访问的顶点使用位压缩表示形式时,此方法可节省内存,因为您只需要记住距离的最低2位即可。这对您来说并不容易。

  2. 您可以直接记住每个访问过的单元格的前身,而当找到终点时,只需将所有这些链接追溯到起点即可。

您可能应该使用方法(2)。

我建议您用visited替换当前效率非常低的std::unordered_map向量,该向量将每个访问的顶点映射到其前身的索引。