小白今天在学习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,怎么说呢,自己能看懂就可以了叭 )