题意:三维迷宫,可以往前后左右上下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