三维BFS

小白今天在学习BFS,跟着kuangbin大佬刷题emm,刷了几道三维BFS的题,今天记录一下。

首先,要搞清楚三维数组各个维数都代表着什么,就比如 maps[x][y][z], x代表块数,y代表每块的行,z代表每块的列,在下面有个杭电的题就有这个坑。。
要用一个三维数组将地图读入,还要有一个同样大小的三维数组来记录该地方是否被走过。

poj 2251
题目大意就是你在一个三维空间,给你起始位置还有目标位置,问你能不能从起始位置到达终止位置,如果可以,要输出所走的时间(每步都是1分钟),如果不可以,输出“Trapped!”。
此题要注意,题目并没有明确给出起始位置和终止位置,需要在读图的时候记录,如果是“S”,则是起始位置,如果是“E”,则是终止位置。
话不多说,上代码

#include <iostream>
#include <queue>
#include <string.h>
using namespace std;
int sx,sy,sz,ex,ey,ez,l,r,c;
char maps[31][31][31];//读取地图
int vis[31][31][31];//标记是否走过
int dir[6][3]=
{
    {1,0,0},
    {-1,0,0},
    {0,1,0},
    {0,-1,0},
    {0,0,1},
    {0,0,-1},
};
struct node
{
    int x;
    int y;
    int z;
    int step;
};
bool check(int x,int y,int z)
{
    if(x<0||y<0||z<0||x>=l||y>=r||z>=c)
        return false;
    else
    {
        if(maps[x][y][z]=='#')
            return false;
        else
        if(vis[x][y][z]==1)
            return false;
    }
    return true;
}
int bfs()
{
    node start,next;
    start.x=sx;
    start.y=sy;
    start.z=sz;
    start.step=0;
    queue<node>q;
    q.push(start);
    while(!q.empty())
    {
        node tmp=q.front();
        q.pop();
        if(tmp.x==ex&&tmp.y==ey&&tmp.z==ez)
            return tmp.step;
        for(int i=0;i<6;i++)
        {
            next=tmp;
            next.x+=dir[i][0];
            next.y+=dir[i][1];
            next.z+=dir[i][2];
            if(check(next.x,next.y,next.z))
            {
                vis[next.x][next.y][next.z]=1;
                next.step++;
                q.push(next);
            }
        }
    }
    return -1;
}
int main()
{
    while(cin>>l>>r>>c&&l+r+c)
    {
        memset(vis,0,sizeof(vis));
        memset(maps,0,sizeof(maps));
        for(int i=0;i<l;i++)
        {
            for(int j=0;j<r;j++)
            {
                cin>>maps[i][j];
                for(int k=0;k<c;k++)
                {
                    if(maps[i][j][k]=='S')
                    {
                        sx=i;sy=j;sz=k;
                    }
                    else
                        if(maps[i][j][k]=='E')
                    {
                        ex=i;ey=j;ez=k;
                    }
                }
            }
        }
        int ans=bfs();
        if(ans==-1)
            cout<<"Trapped!"<<endl;
        else
            cout<<"Escaped in "<<ans<<" minute(s)."<<endl;
    }
}

hdoj 1240
此题一定要注意给出的x,y,z都是什么意义,我一开始写的时候没注意,最后发现,题中给的x,y,z的意义与一般的是完全相反的,题中的z是块数,y是行数,x是列数,因此在读入的时候将第一个数读成z,第二个数读成y,第三个数读成x就可以了

#include <iostream>
#include <queue>
#include <string.h>
using namespace std;
char maps[11][11][11];
int vis[11][11][11];
int n,sx,sy,sz,ex,ey,ez;
int dir[6][3]=
{
    {1,0,0},
    {-1,0,0},
    {0,1,0},
    {0,-1,0},
    {0,0,1},
    {0,0,-1},
};
struct node
{
    int x;
    int y;
    int z;
    int step;
};
bool check(int x,int y,int z)
{
    if(x<0||y<0||z<0||x>=n||y>=n||z>=n)
        return false;
    else
    {
        if(maps[x][y][z]=='X')
            return false;
        else
            if(vis[x][y][z]==1)
            return false;
    }
    return true;
}
int bfs()
{
    node start,next;
    start.x=sx;
    start.y=sy;
    start.z=sz;
    start.step=0;
    queue<node>q;
    q.push(start);
    while(!q.empty())
    {
        node tmp=q.front();
        q.pop();
        if(tmp.x==ex&&tmp.y==ey&&tmp.z==ez)
            return tmp.step;
        for(int i=0;i<6;i++)
        {
            next=tmp;
            next.x+=dir[i][0];
            next.y+=dir[i][1];
            next.z+=dir[i][2];
            if(check(next.x,next.y,next.z))
            {
                vis[next.x][next.y][next.z]=1;
                next.step++;
                q.push(next);
            }
        }
    }
    return -1;
}
int main()
{
    string s;
    while(cin>>s>>n)
    {
        memset(maps,0,sizeof(maps));
        memset(vis,0,sizeof(vis));
        for(int i=0;i<n;i++)
        {
            for(int j=0;j<n;j++)
                cin>>maps[i][j];
        }
        cin>>sz>>sy>>sx>>ez>>ey>>ex;
        cin>>s;
        int ans=bfs();
        if(ans==-1)
            cout<<"NO ROUTE"<<endl;
        else
            cout<<n<<" "<<ans<<endl;
    }
}

hdoj 1253
此题数据量较大,输入时要用scanf(),还有就是最后得到结果后与题中给的时间比较(相等时也算出逃成功)
刚刚阿伟又改了一下代码,检查了好长时间,最后发现是自己没有加memset

#include <iostream>
#include <queue>
#include <string.h>
#include <cstdio>
using namespace std;
int a,b,c,sum;
int maps[51][51][51];
int vis[51][51][51];
int dir[6][3]=
{
    {1,0,0},
    {-1,0,0},
    {0,1,0},
    {0,-1,0},
    {0,0,1},
    {0,0,-1},
};
struct node
{
    int x;
    int y;
    int z;
    int step;
};
bool check(int x,int y,int z,int step)
{
    if(x<0||y<0||z<0||x>=a||y>=b||z>=c)
        return false;
    else
    {
        if(maps[x][y][z]==1)
            return false;
        else
            if(vis[x][y][z]==1)
            return false;
        else
            if(step>sum)
            return false;
    }
    return true;
}
int bfs()
{
    node start,next;
    queue<node>q;
    start.x=0;
    start.y=0;
    start.z=0;
    start.step=0;
    q.push(start);
    while(!q.empty())
    {
        node tmp=q.front();
        q.pop();
        if(tmp.x==a-1&&tmp.y==b-1&&tmp.z==c-1)
            return tmp.step;
        for(int i=0;i<6;i++)
        {
            next=tmp;
            next.x+=dir[i][0];
            next.y+=dir[i][1];
            next.z+=dir[i][2];
            if(check(next.x,next.y,next.z,next.step))
            {
                vis[next.x][next.y][next.z]=1;
                next.step++;
                q.push(next);
            }
        }
    }
    return -1;
}
int main()
{
    int n;
    cin>>n;
    while(n--)
    {
        memset(vis,0,sizeof(vis));//初始化不能忘!!!(破音~)
        memset(maps,0,sizeof(maps));//同款破音~
        scanf("%d%d%d%d",&a,&b,&c,&sum);
        for(int i=0;i<a;i++)
        {
            for(int j=0;j<b;j++)
            {
                for(int k=0;k<c;k++)
                    scanf("%d",&maps[i][j][k]);
            }
        }
        int ans=bfs();
        if(ans!=-1)
        {
            if(ans<=sum)
                cout<<ans<<endl;
            else
                cout<<-1<<endl;
        }
        else
            cout<<-1<<endl;
    }
}

咳咳,
综上所述,今天做的这三个题,套路都差不多,思想也一致,只有小部分细节,不过也不能忽视小的细节。
(之前看他们的代码,总觉得没有注释好难受,因为我看不懂 ,现在发现我也没有写注释emm,怎么说呢,自己能看懂就可以了叭

发布了32 篇原创文章 · 获赞 12 · 访问量 1395

猜你喜欢

转载自blog.csdn.net/qq_18873031/article/details/98492463