Description
Input
Output
Escaped in x minute(s).
Trapped!
Sample Input
3 4 5
S....
.###.
.##..
###.#
#####
#####
##.##
##...
#####
#####
#.###
####E
1 3 3
S##
#E#
###
0 0 0
Sample Output
Escaped in 11 minute(s).
Trapped!
仍然是一个走迷宫的问题,只不过这回变成了3D迷宫,万变不离其宗,当然还是要搜索,但考虑到题目要求输出走出迷宫的最短路线长度,而不是简单的判断是否可以走出,所以我们这里使用BFS,虽然题目并不难,但一开始图简单,就用的queue,加上动态创建结构体对象,结果华丽超时,无奈又重新自己写了一个队列,本想省点空间,结果看起来还是时间比较珍贵,这里的输入要稍微注意一下,如果是cin没有什么,但如果使用scanf,就需要用getchar()吸收掉回车,否则读入的地图是完全混乱的,BFS里计算步数是通过计算树的高度实现的,这个很好理解,BFS本身就是一层一层向下找,因此没走一层就相当于走了一步,六个方向依然是通过数组+循环实现,这里,首先上超时的代码,因为我觉得很省空间
#include<iostream> #include<stdio.h> #include<queue> using namespace std; char map[31][31][31]; int dirx[6]={0,0,0,0,-1,1}; int diry[6]={0,0,-1,1,0,0}; int dirz[6]={1,-1,0,0,0,0}; int step; int visited[31][31][31]; int l,r,c; struct Point { Point(int l,int r,int c,int d) { x=r; y=c; z=l; deep=d; } int x,y,z,deep; }; bool BFS(int sl,int sr,int sc) { int i; bool flag=false; queue<Point*> q; q.push(new Point(sl,sr,sc,0)); //Point *a=q.front(); //cout<<a->x<<' '<<a->y<<' '<<a->z; while(!q.empty()) { Point *t=q.front(); q.pop(); //cout<<t->z<<' '<<t->x<<' '<<t->y<<endl; //cout<<map[t->z][t->x][t->y]<<' '; //cout<<t->x<<' '<<t->y<<' '<<t->z<<endl; if(map[t->z][t->x][t->y]=='E') { step=t->deep; return true; } visited[t->z][t->x][t->y]=1; for(i=0;i<6;i++) { int x0,y0,z0,deep0; z0=t->z+dirz[i]; x0=t->x+dirx[i]; y0=t->y+diry[i]; deep0=t->deep; //cout<<z0<<' '<<x0<<' '<<y0<<endl; if(map[z0][x0][y0]!='#'&&visited[z0][x0][y0]==0) { if(x0>=0&&x0<r&&y0>=0&&y0<c&&z0>=0&&z0<l) { q.push(new Point(z0,x0,y0,deep0+1)); } } } } return false; } int main() { int i,j,k; int x,y,z; while(scanf("%d%d%d\n",&l,&r,&c)!=EOF,l&&r&&c) { step=0; for(i=0;i<l;i++) { for(j=0;j<r;j++) { for(k=0;k<c;k++) { scanf("%c",&map[i][j][k]); visited[i][j][k]=0; if(map[i][j][k]=='S') { x=j; y=k; z=i; } } getchar(); } getchar(); } for(i=0;i<l;i++) { for(j=0;j<r;j++) { for(k=0;k<c;k++) { cout<<map[i][j][k]; } cout<<endl; } cout<<endl; } if(BFS(z,x,y)) { cout<<"Escaped in "<<step<<" minute(s)."<<endl; } else cout<<"Trapped!"<<endl; } return 0; }这里要注意三个方向与我们的三维坐标系的对应,可以说有点混乱,主要是因为三维数组虽然可以表示三维空间,但对应不太一样,下面是自己写了队列的正确代码
#include<iostream> #include<stdio.h> #include<queue> using namespace std; char map[31][31][31]; int dirx[6]={0,0,0,0,-1,1}; int diry[6]={0,0,-1,1,0,0}; int dirz[6]={1,-1,0,0,0,0}; int step; int visited[31][31][31]; int l,r,c; struct Point { int x,y,z,deep; }q[30000]; bool BFS(int sl,int sr,int sc) { int i,rear,front; q[0].z=sl; q[0].x=sr; q[0].y=sc; rear=0; front=0; visited[sl][sr][sc]=1; while(front<=rear) { for(i=0;i<6;i++) { int x0,y0,z0,deep0; z0=q[front].z+dirz[i]; x0=q[front].x+dirx[i]; y0=q[front].y+diry[i]; deep0=q[front].deep; if(map[z0][x0][y0]!='#'&&visited[z0][x0][y0]==0) { if(x0>=0&&x0<r&&y0>=0&&y0<c&&z0>=0&&z0<l) { visited[z0][x0][y0]=1; rear++; q[rear].x=x0; q[rear].y=y0; q[rear].z=z0; q[rear].deep=q[front].deep+1; if(map[z0][x0][y0]=='E') { step=q[rear].deep; return true; } } } } front++; } return false; } int main() { int i,j,k; int x,y,z; while(scanf("%d%d%d",&l,&r,&c)!=EOF,l&&r&&c) { getchar(); step=0; for(i=0;i<l;i++) { for(j=0;j<r;j++) { for(k=0;k<c;k++) { scanf("%c",&map[i][j][k]); visited[i][j][k]=0; if(map[i][j][k]=='S') { x=j; y=k; z=i; } } getchar(); } getchar(); } if(BFS(z,x,y)) { printf("Escaped in %d minute(s).\n",step); } else printf("Trapped!\n"); } return 0; }其实写个队列并不是很麻烦,开始为了便于理解我们可以使用STL,但这东西用好了还行,一不留神就会出问题,尤其是时间上的,建议大家尽量避免使用,尤其是在你不知道STL某些容器的时间消耗的时候