题意:三维迷宫,可以往前后左右上下8个方向移动。
思路:8个方向的移动对应8种三维坐标的变化。这里三维坐标还是按照高、行、列为x、y、z的顺序。和二维迷宫类似,但二维可以把行列统一为 行*长度+列,三维却不可以,只能用结构体。直接用结构体数组表示队列即可,结构体之间可以直接赋值。
Code:
//#define LOCAL #include<stdio.h> #include<stdlib.h> #include<string.h> struct cell { int gao,hang,lie; }; void process(struct cell st,int nl,int nr,int nc); void print(int nl,int nr,int nc); char maze[35][35][35]; int dx[]={0,0,0,0,1,-1}; int dy[]={-1,1,0,0,0,0}; int dz[]={0,0,-1,1,0,0}; int main() { #ifdef LOCAL freopen("532.in","r",stdin); freopen("532.out","w",stdout); #endif int nl,nr,nc; while((scanf("%d%d%d",&nl,&nr,&nc)==3) && nl&&nr&&nc) { memset(maze,0,sizeof(maze)); getchar();//不要忘了弃置最开始的换行符 int sl=0,sr=0,sc=0; for(int i=0;i<nl;++i) { for(int j=0;j<nr;++j) { for(int k=0;k<nc;++k) { char c=getchar(); maze[i][j][k]=c; if(c=='S') {sl=i;sr=j;sc=k;}//起点位置 } getchar();//弃置每行后的换行 } getchar();//弃置每个块后的空行 } //print(nl,nr,nc); struct cell scl={sl,sr,sc}; //printf("scl:%d %d %d\necl:%d %d %d\n",scl.hang,scl.lie,scl.gao); process(scl,nl,nr,nc); } //system("pause"); return 0; } void process(struct cell st,int nl,int nr,int nc) { struct cell queue[30*30*30+5]; int dist[nl][nr][nc]; memset(dist,0,sizeof(dist)); //dist[st->gao][st->hang][st->lie]=-1;//用dist矩阵也来判断是否访问过,没访问过的为0,初始点到自己距离设为-1以区分 int vis[nl][nr][nc]; memset(vis,0,sizeof(vis)); vis[st.gao][st.hang][st.lie]=1; int front=0,rear=0; queue[rear++]=st; bool flag=false; int num=0; while(front<rear) { struct cell hd=queue[front++]; int x=hd.gao; int y=hd.hang; int z=hd.lie; for(int i=0;i<6;++i) { int nx=x+dx[i]; int ny=y+dy[i]; int nz=z+dz[i]; if(nx>=0 && nx<nl && ny>=0 && ny<nr && nz>=0 && nz<nc && (vis[nx][ny][nz]==0)) { if(maze[nx][ny][nz]=='E') { flag=true; num=dist[nx][ny][nz]=dist[x][y][z]+1; break; } else if(maze[nx][ny][nz]=='.') { vis[nx][ny][nz]=1; dist[nx][ny][nz]=dist[x][y][z]+1; struct cell ncl={nx,ny,nz};//额,这里初始化的顺序和结构体声明顺序没有一致,导致了错误~ queue[rear++]=ncl; } } } if(flag) break; } if(flag) printf("Escaped in %d minute(s).\n",num); else printf("Trapped!\n"); }
这里遇到了一系列的错误。。首先,觉得结构体赋值可能耗时,所以用了指针,结构体指针队列。但在下面else-if语句块里创建的结构体变量,取址加入队列,而这个变量是块作用域的,块结束时即销毁!!!(以前知道注意不能把指向局部变量的指针作为返回值,这里这种情况倒是没想到。。指针坑太多。。)
总结:不能在块外部使用块作用域变量的指针。RE错误。
第二,在构建新的结构体时,初始化的顺序没有和结构体中变量声明顺序一致,也是个问题。
第三,bfs注意要设置结点是否访问过。开始我用dist数组是否为0来表示,但是起点到自身的距离和未访问过的结点一样dist都是0。于是把起点到自身的dist设置为-1,这样引来更大的麻烦,因为本来dist为1的这样就变成了0。。。
所以总结一下,设置是否访问过的方法:要么直接用vis数组来标识即可,或者在结构体中设置一个位表示是否访问过,
要么用dist数组兼职的话,dist为0即未访问过,但是起点到自身也是0。这一点,不要修改起点到自身的距离值,而是加一个判断,判断各维索引表示的位置不是起点(参见上一题439的实现)。
错误的用指针的代码:
#define LOCAL #include<stdio.h> #include<stdlib.h> #include<string.h> struct cell { int gao,hang,lie; }; void process(const struct cell *st,int nl,int nr,int nc); void print(int nl,int nr,int nc); char maze[35][35][35]; int dx[]={0,0,0,0,1,-1}; int dy[]={-1,1,0,0,0,0}; int dz[]={0,0,-1,1,0,0}; int main() { #ifdef LOCAL freopen("532.in","r",stdin); //freopen("532.out","w",stdout); #endif int nl,nr,nc; while((scanf("%d%d%d",&nl,&nr,&nc)==3) && nl&&nr&&nc) { memset(maze,0,sizeof(maze)); getchar();//不要忘了弃置最开始的换行符 int sl=0,sr=0,sc=0; //int el,er,ec; for(int i=0;i<nl;++i) { for(int j=0;j<nr;++j) { for(int k=0;k<nc;++k) { char c=getchar(); maze[i][j][k]=c; if(c=='S') {sl=i;sr=j;sc=k;}//起点位置 //else if(c=='E') //{el=i;er=j;ec=k;} } getchar();//弃置每行后的换行 } getchar();//弃置每个块后的空行 } //print(nl,nr,nc); struct cell scl={sl,sr,sc}; //struct cell ecl={el,er,ec}; //printf("scl:%d %d %d\necl:%d %d %d\n",scl.hang,scl.lie,scl.gao); process(&scl,nl,nr,nc); } //system("pause"); return 0; } void process(const struct cell *st,int nl,int nr,int nc) { const struct cell *queue[30*30*30+5]; int dist[nl][nr][nc]; memset(dist,0,sizeof(dist)); //dist[st->gao][st->hang][st->lie]=-1;//用dist矩阵也来判断是否访问过,没访问过的为0,初始点到自己距离设为-1以区分 int vis[nl][nr][nc]; memset(vis,0,sizeof(vis)); vis[st->gao][st->hang][st->lie]=1; int front=0,rear=0; queue[rear++]=st; bool flag=false; int num=0; while(front<rear) { const struct cell *hd=queue[front++]; int x=hd->gao; int y=hd->hang; int z=hd->lie; for(int i=0;i<6;++i) { int nx=x+dx[i]; int ny=y+dy[i]; int nz=z+dz[i]; if(nx>=0 && nx<nl && ny>=0 && ny<nr && nz>=0 && nz<nc && (vis[nx][ny][nz]==0)) { if(maze[nx][ny][nz]=='E') { flag=true; num=dist[nx][ny][nz]=dist[x][y][z]+1; break; } else if(maze[nx][ny][nz]=='.') { vis[nx][ny][nz]=1; dist[nx][ny][nz]=dist[x][y][z]+1; struct cell ncl={nx,ny,nz};//额,这里初始化的顺序和结构体声明顺序没有一致,导致了错误~ queue[rear++]=&ncl; } } } if(flag) break; } if(flag) printf("Escaped in %d minute(s).\n",num); else printf("Trapped!\n"); } void print(int nl,int nr,int nc) { for(int i=0;i<nl;++i) for(int j=0;j<nr;++j) maze[i][j][nc]='\0'; for(int i=0;i<nl;++i) { for(int j=0;j<nr;++j) { printf("%s\n",maze[i][j]); } printf("\n"); } }
原文地址:http://blog.csdn.net/buxizhizhou530/article/details/43194377