【问题标题】:3D Maze solving with BFS. How to get a full shortest path to the end point if found in C++?使用 BFS 解决 3D 迷宫问题。如果在 C++ 中找到,如何获得到终点的完整最短路径?
【发布时间】:2020-09-06 23:27:10
【问题描述】:

我正在尝试实现 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,y,z) accessible
};
void BFS(Maze &maze,vector< pair<int, 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, pair<int, int> > > visited(maze.grids);
    visited.push_back(make_pair(xx, make_pair(yy, zz)));
    result.push_back(make_pair(xx, make_pair(yy, 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,make_pair(yy,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,yy,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;
    }
}

【问题讨论】:

  • 嗨,欢迎来到 Stack Overflow。您遇到的确切问题是什么?您的代码是否有效,不是吗?哪个部分不起作用?你试过什么?如果您有一个minimal reproducible example 和一个非常有针对性的问题,您的问题将获得更多关注。
  • @NathanWride 嗨!我的问题是我能够找到目标,但我不知道如何获得最短路径并将其打印出来。我正在考虑使用父母/孩子的概念,但我不确定它是否有效。很抱歉造成混乱。
  • 你已经有了基本的想法,你正在遍历相邻的单元格并将它们添加到搜索的单元格列表中。接下来你需要做的是跟踪一个单元格“分数”(在最简单的解决方案中,它是前一个单元格的分数加一),一旦你找到了你需要的目标,你需要在你的列表中向后工作(开始从目标)找到哪个相邻单元格具有下一个最小值。完成后,您将获得一个从目标开始到起点结束的单元格列表,这将是最短路径。
  • 我建议阅读更多关于 Dijkstra's algorithmA*

标签: c++ vector breadth-first-search maze


【解决方案1】:

常用的方法有两种:

  1. 您会记住每个访问过的单元格从起点开始的距离,然后当您找到终点时,您会沿着每一步距离缩短的路径回到起点。当您可以对访问的顶点使用位压缩表示时,此方法可以节省内存,因为您只需要记住距离的最低 2 位。这不适用于您。

  2. 您直接记住每个访问过的单元格的前身,当您找到结尾时,您只需按照所有这些链接回到开头。

你应该使用方法(2)。

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-03-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-04-08
    相关资源
    最近更新 更多