微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

为什么这个 BFS 队列大小如此之大?

如何解决为什么这个 BFS 队列大小如此之大?

我最近在研究 BFS 算法。我用这个算法做了一个迷宫求解程序。这是我的代码

#include<iostream>
#include<cmath>
#include<sstream>
#include<vector>
#include<queue>
#include <unistd.h>

using namespace std;
int m,n;

inline int indexFor(int x,int y) {
    return (x-1) + m*(y-1);
}


int main() {

    FILE *file = fopen("test_case","r"); // test_case file

    //build maze
    fscanf(file,"%d",&m);
    fscanf(file,&n);

    vector<int> grid((m+1)*(n+1));

    for(int i=1;i<=m;i++) {
        for(int j =1;j<=n;j++) {
            int k;
            fscanf(file,&k);
            grid[indexFor(i,j)] = k;
        }
    }

    int startX,startY,endX,endY;
    fscanf(file,&startX);
    fscanf(file,&startY);
    fscanf(file,&endX);
    fscanf(file,&endY);

    //bfs starts
    queue<int> x,y;

    x.push(1);
    y.push(1);

    vector<int> visited((m+1)*(n+1),0);

    vector<vector<int>> path_track((m+1)*(n+1),vector<int>(2,0));

    while(x.size()>0) {
        int k = x.front(),l = y.front();
        x.pop();
        y.pop();

        visited[indexFor(k,l)]=1;
        // this part for printing each steps
        cout << "\033[2J\033[H";
        cout << "queue size: " << x.size()<<endl;
        for(int i=1;i<=m;i++) {
        for(int j =1;j<=n;j++) {
            if(visited[indexFor(i,j)]==1) cout << "* ";
            else {
                if(grid[indexFor(i,j)]==0) {
                    cout << ". ";
                } else {
                    cout << "# ";
                }
            }
        }
        cout << endl;
        }
        usleep(10);

        if(k-1>0) {
            if(grid[indexFor(k-1,l)] != 1 && visited[indexFor(k-1,l)]!=1) {
            x.push(k-1);
            y.push(l);            
            path_track[indexFor(x.back(),y.back())] = {k,l};
        }}

        if((k+1)<=m) {
            if(grid[indexFor(k+1,l)] != 1 && visited[indexFor(k+1,l)]!=1) {
            x.push(k+1);
            y.push(l);
            //cout << "Path_track: "<<x.back() << "," << y.back() << " : " << k << "," << l <<endl;
            path_track[indexFor(x.back(),l};
        }}

        if(l-1>0) {
            if(grid[indexFor(k,l-1)] != 1 && visited[indexFor(k,l-1)]!=1) {
            x.push(k);
            y.push(l-1);
            path_track[indexFor(x.back(),l};
        }}

        if(l+1<=n) {
            if(grid[indexFor(k,l+1)] != 1 && visited[indexFor(k,l+1)]!=1) {
            x.push(k);
            y.push(l+1);
            path_track[indexFor(x.back(),l};
        }}
    }

        cout << "\033[2J\033[H";

    vector<vector<int>> path;

    path.push_back({endX,endY});

    while(endX!=0&&endY!=0) {        
        int kx = endX,ky = endY;
        endX = path_track[indexFor(kx,ky)][0];
        endY = path_track[indexFor(kx,ky)][1];
        path.push_back({endX,endY});
    }
    path.pop_back();
    
    
    if(path[path.size()-1][0] == startX && path[path.size()-1][1] == startY)
    {

    for(vector<int> l:path)  grid[indexFor(l[0],l[1])] = 8;
    for(int i=1;i<=m;i++) {
        for(int j =1;j<=n;j++) {
            if(grid[indexFor(i,j)]==8) {
                cout << "X ";
            } else {
                if(grid[indexFor(i,j)]==0) {
                    cout << ". ";
                } else {
                    cout << "# ";
                }
            }
        }
        cout << endl;
    }
    } else {
        cout << "No path found\n";
        for(vector<int> l:path)  grid[indexFor(l[0],j)]==0) {
                    cout << ". ";
                } else {
                    cout << "# ";
                }
            }
        }
        cout << endl;
    }
    }
    
    //cout<<path_track[indexFor(2,2)][0]<<","<<path_track[indexFor(2,2)][1]<<endl;

    




    return 0;
}

我为这个问题制作了一个 maze_generator :

#include <iostream>
#include <vector>

using namespace std;
int m,int y) {
    return m * (x-1) + (y-1);
}

int main() {


    srand(time(nullptr));

    FILE * f = fopen("test_case","w");
    
    cin >> m;
    cin >> n;
    vector<int> grid(m*n,0);

    fprintf(f,"%d %d\n",m,n);

    for(int i = 0; i<grid.size();i++) {        
        int k = (rand()%7);
        if(i == 0 || i==grid.size()-1 ) k = 0;
        grid[i] = k<5?0:1;
    }

    grid[indexFor(m,n)] = 0;

    for(int i = 1;i<=m;i++) {
        for(int j = 1; j<=n;j++) {
            cout << grid[indexFor(i,j)] << " ";
            fprintf(f,"%d ",grid[indexFor(i,j)]);
        }
        cout<<endl;
        fprintf(f,"\n");
    }
    fprintf(f,"1 1\n%d %d",n);


    return 0;
}

生成了这个 test_case:

21 50
0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 1 1 0 1 0 0 0 1 0 0 0 0 0 0 1 0 0 1 0 0 0 1 0 0 0 1 1 1 0 0 1 0 1 
0 0 0 1 0 0 0 0 0 0 1 0 0 1 0 0 0 1 0 0 0 1 1 1 0 0 1 0 1 0 0 0 1 0 0 0 1 0 1 1 0 0 0 1 0 1 0 0 0 0 
1 1 1 0 0 1 0 1 0 0 0 1 0 0 0 1 0 1 1 0 0 0 1 0 1 0 0 0 0 0 0 0 1 0 0 1 0 0 0 0 1 0 0 0 1 1 0 0 0 0 
0 1 0 1 0 0 0 0 0 0 0 1 0 0 1 0 0 0 0 1 0 0 0 1 1 0 0 0 0 1 0 1 1 0 1 1 0 0 0 0 1 0 0 0 0 0 0 0 0 0 
0 0 1 1 0 0 0 0 1 0 1 1 0 1 1 0 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 1 0 0 0 0 1 0 0 0 0 0 0 1 1 1 1 0 0 0 
0 0 0 0 0 0 0 0 1 0 1 0 0 0 0 1 0 0 0 0 0 0 1 1 1 1 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 
0 1 1 1 1 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 1 0 1 0 0 0 0 
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 1 0 1 0 0 0 0 0 0 0 0 0 1 0 1 1 1 1 0 0 0 1 0 0 0 0 1 0 
0 1 0 1 0 0 0 0 0 0 0 0 0 1 0 1 1 1 1 0 0 0 1 0 0 0 0 1 0 0 1 0 1 0 0 0 0 0 0 1 0 1 0 0 0 0 1 0 0 0 
0 1 0 0 0 0 1 0 0 1 0 1 0 0 0 0 0 0 1 0 1 0 0 0 0 1 0 0 0 0 0 1 1 0 0 1 0 1 0 0 1 0 0 0 0 0 1 1 0 0 
0 0 0 0 1 0 0 0 0 0 1 1 0 0 1 0 1 0 0 1 0 0 0 0 0 1 1 0 0 0 1 0 0 1 1 0 0 0 0 0 0 0 1 1 1 0 1 1 0 1 
0 0 0 0 1 1 0 0 0 1 0 0 1 1 0 0 0 0 0 0 0 1 1 1 0 1 1 0 1 0 1 1 0 0 0 0 1 0 1 0 0 0 0 0 1 0 0 0 0 1 
1 1 1 0 1 1 0 1 0 1 1 0 0 0 0 1 0 1 0 0 0 0 0 1 0 0 0 0 1 0 1 0 1 0 0 0 0 1 0 0 0 1 0 1 0 1 0 1 0 0 
0 0 1 0 0 0 0 1 0 1 0 1 0 0 0 0 1 0 0 0 1 0 1 0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 0 0 0 0 0 
0 1 0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 0 0 0 0 0 1 1 0 0 0 1 0 0 0 1 0 0 0 0 0 0 1 0 1 0 1 
1 0 1 0 0 0 0 0 1 1 0 0 0 1 0 0 0 1 0 0 0 0 0 0 1 0 1 0 1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 1 1 0 0 1 1 
0 0 0 1 0 1 0 1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 1 1 0 0 1 1 0 0 0 1 1 0 0 0 1 1 1 1 0 0 1 0 0 0 0 0 0 
0 0 1 1 0 0 1 1 0 0 0 1 1 0 0 0 1 1 1 1 0 0 1 0 0 0 0 0 0 1 0 1 0 0 0 0 1 0 0 0 0 0 1 1 1 0 0 0 0 0 
0 1 0 0 0 0 0 0 1 0 1 0 0 0 0 1 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 1 0 0 0 0 0 1 1 1 0 0 0 0 0 0 1 0 0 1 
1 1 1 0 0 0 0 0 0 0 1 0 0 0 0 0 1 1 1 0 0 0 0 0 0 1 0 0 1 1 0 0 0 1 0 1 0 0 0 0 0 0 0 0 0 0 1 0 1 0 
0 0 0 0 1 0 0 1 1 0 0 0 1 0 1 0 0 0 0 0 0 0 0 0 0 1 0 1 0 0 0 0 0 0 0 0 0 1 1 1 1 0 0 1 0 1 1 1 0 0 
1 1
21 50

在测试用例中,最后两行代表迷宫的起点和终点。对于迷宫,0 表示自由路径,1 表示墙壁。第一行表示迷宫的大小。

问题是,当我解决它时,对于这个特定的 test_case,队列大小跃升至 130k+。有什么我想念的吗?还是正常的?

solving maze

解决方法

我解决了这个问题。看起来我需要使用另一个数组进行队列映射来检查一个点是否已经排队。这是最终的解决方案:


#include<iostream>
#include<cmath>
#include<sstream>
#include<vector>
#include<queue>
#include <unistd.h>

using namespace std;
int m,n;

inline int indexFor(int x,int y) {
    return (x-1) + m*(y-1);
}


int main() {

    FILE *file = fopen("test_case","r");

    
    fscanf(file,"%d",&m);
    fscanf(file,&n);

    vector<int> grid((m+1)*(n+1));

    for(int i=1;i<=m;i++) {
        for(int j =1;j<=n;j++) {
            int k;
            fscanf(file,&k);
            grid[indexFor(i,j)] = k;
        }
    }

    int startX,startY,endX,endY;
    fscanf(file,&startX);
    fscanf(file,&startY);
    fscanf(file,&endX);
    fscanf(file,&endY);


    queue<int> x,y;

    x.push(1);
    y.push(1);

    vector<int> visited((m+1)*(n+1),0);
    vector<int> queued((m+1)*(n+1),0); // <-- THIS IS WHAT I ADDED

    vector<vector<int>> path_track((m+1)*(n+1),vector<int>(2,0));

    while(x.size()>0) {
        int k = x.front(),l = y.front();
        x.pop();
        y.pop();


        visited[indexFor(k,l)]=1;

        cout << "\033[2J\033[H";
        cout << "queue size: " << x.size()<<endl;
        for(int i=1;i<=m;i++) {
        for(int j =1;j<=n;j++) {
            if(visited[indexFor(i,j)]==1) cout << "* ";
            else {
                if(grid[indexFor(i,j)]==0) {
                    cout << ". ";
                } else {
                    cout << "# ";
                }
            }
        }
        cout << endl;
        }
        usleep(10000);

        if(k-1>0) {
            if(grid[indexFor(k-1,l)] != 1 && visited[indexFor(k-1,l)]!=1&&!queued[indexFor(k-1,l)]) {
            x.push(k-1);
            y.push(l);
            queued[indexFor(x.back(),y.back())] = 1;       
            path_track[indexFor(x.back(),y.back())] = {k,l};
        }}

        if((k+1)<=m) {
            if(grid[indexFor(k+1,l)] != 1 && visited[indexFor(k+1,l)]!=1&&!queued[indexFor(k+1,l)]) {
            x.push(k+1);
            y.push(l);
            //cout << "Path_track: "<<x.back() << "," << y.back() << " : " << k << "," << l <<endl;
            path_track[indexFor(x.back(),l};
            queued[indexFor(x.back(),y.back())] = 1; 
        }}

        if(l-1>0) {
            if(grid[indexFor(k,l-1)] != 1 && visited[indexFor(k,l-1)]!=1&&!queued[indexFor(k,l-1)]) {
            x.push(k);
            y.push(l-1);
            path_track[indexFor(x.back(),y.back())] = 1; 
        }}

        if(l+1<=n) {
            if(grid[indexFor(k,l+1)] != 1 && visited[indexFor(k,l+1)]!=1&&!queued[indexFor(k,l+1)]) {
            x.push(k);
            y.push(l+1);
            queued[indexFor(x.back(),y.back())] = 1; 
            path_track[indexFor(x.back(),l};
        }}
    }

        cout << "\033[2J\033[H";

    vector<vector<int>> path;

/*
    for(int i=1;i<=m;i++) {
        for(int j =1;j<=m;j++) {
            cout << path_track[indexFor(i,j)][0] << "," << path_track[indexFor(i,j)][1]<< " ";
        }
        cout << endl;
    }
*/
    path.push_back({endX,endY});

    while(endX!=0&&endY!=0) {        
        int kx = endX,ky = endY;
        endX = path_track[indexFor(kx,ky)][0];
        endY = path_track[indexFor(kx,ky)][1];
        path.push_back({endX,endY});
    }
    path.pop_back();
    
    
    if(path[path.size()-1][0] == startX && path[path.size()-1][1] == startY)
    {

    for(vector<int> l:path)  grid[indexFor(l[0],l[1])] = 8;
    for(int i=1;i<=m;i++) {
        for(int j =1;j<=n;j++) {
            if(grid[indexFor(i,j)]==8) {
                cout << "X ";
            } else {
                if(grid[indexFor(i,j)]==0) {
                    cout << ". ";
                } else {
                    cout << "# ";
                }
            }
        }
        cout << endl;
    }
    } else {
        cout << "No path found\n";
        for(vector<int> l:path)  grid[indexFor(l[0],j)]==0) {
                    cout << ". ";
                } else {
                    cout << "# ";
                }
            }
        }
        cout << endl;
    }
    }
    
    //cout<<path_track[indexFor(2,2)][0]<<","<<path_track[indexFor(2,2)][1]<<endl;

    




    return 0;
}

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。