题目:UVA532 Dungeon Master
类型:bfs 队列 三维bfs
主要错误:标记已走过的点不及时
- 第一次标记的位置如下注释,在判断可达到后标记,标的是当前的位置(
我在想啥呢),会出现两个问题:- 如果当前位置没有路可走,那么当前位置不会被标记
- 只标记当前位置会导致位置重复压入,原则上说每个位置只能让它压入一次,所以必须一旦压入就立马标记已走过
while(que.size())
{
A a=que.front();
que.pop();
for(int i=-1;i<=1;i+=2)
for(int j=0;j<3;j++)
{
int nx=a.x+i*next1[j][0],ny=a.y+i*next1[j][1],nz=a.z+i*next1[j][2];
if(nx>=0&&nx<n&&ny>=0&&ny<m&&nz>=0&&nz<l&&maze[nz][nx][ny]!='#')
{
if(maze[nz][nx][ny]=='E')
{
cout<<"Escaped in "<<ans[a.z][a.x][a.y]+1<<" minute(s)."<<endl;
goto end;
}
ans[nz][nx][ny]=ans[a.z][a.x][a.y]+1;
maze[a.z][a.x][a.y]='#'; //这里
que.push(A(nx,ny,nz));
}
}
}
- 第二次标记和第一次的错误2一样,仍然会导致相同元素的重复压入
while(que.size())
{
A a=que.front();
que.pop();
maze[a.z][a.x][a.y]='#';//这里
for(int i=-1;i<=1;i+=2)
for(int j=0;j<3;j++)
{
int nx=a.x+i*next1[j][0],ny=a.y+i*next1[j][1],nz=a.z+i*next1[j][2];
if(nx>=0&&nx<n&&ny>=0&&ny<m&&nz>=0&&nz<l&&maze[nz][nx][ny]!='#')
{
if(maze[nz][nx][ny]=='E')
{
cout<<"Escaped in "<<ans[a.z][a.x][a.y]+1<<" minute(s)."<<endl;
goto end;
}
ans[nz][nx][ny]=ans[a.z][a.x][a.y]+1;
que.push(A(nx,ny,nz));
}
}
}
- 最后记得这种多组测试数据放一起的题,每次要还原数组之类的,每次做完检查一下,不要理所当然觉得数据会进行覆盖。
- AC代码:
#include<iostream>
#include<queue>
using namespace std;
const int MAX_N=32;
struct A
{
int x,y,z;
A(int x,int y,int z):x(x),y(y),z(z){}
A(){}
};
int next1[3][3]={{1,0,0},{0,1,0},{0,0,1}};
char maze[MAX_N][MAX_N][MAX_N];
int ans[MAX_N][MAX_N][MAX_N];
int main()
{
ios::sync_with_stdio(false);
int l,n,m;
while(cin>>l>>n>>m&&(l||m||n))
{
A begin,end;
for(int i=0;i<l;i++)
for(int j=0;j<n;j++)
for(int k=0;k<m;k++)
{
cin>>maze[i][j][k];
ans[i][j][k]=0;
if(maze[i][j][k]=='S')begin.x=j,begin.y=k,begin.z=i,maze[i][j][k]='#';
if(maze[i][j][k]=='E')end.x=j,end.y=k,end.z=i;
}
queue<A> que;
que.push(begin);
int a1=-1;
while(que.size())
{
A a=que.front();
que.pop();
if(a.x==end.x&&a.y==end.y&&a.z==end.z)
{
a1=ans[a.z][a.x][a.y];
break;
}
for(int i=-1;i<=1;i+=2)
for(int j=0;j<3;j++)
{
int nx=a.x+i*next1[j][0],ny=a.y+i*next1[j][1],nz=a.z+i*next1[j][2];
if(nx>=0&&nx<n&&ny>=0&&ny<m&&nz>=0&&nz<l&&maze[nz][nx][ny]!='#')
{
maze[nz][nx][ny]='#';
ans[nz][nx][ny]=ans[a.z][a.x][a.y]+1;
que.push(A(nx,ny,nz));
}
}
}
if(a1!=-1)cout<<"Escaped in "<<a1<<" minute(s)."<<endl;
else cout<<"Trapped!"<<endl;
}
return 0;
}
总结:
- 大部分的题目都是压入就标记,记住这一点就对了,压入->标记
- 可移动方向也很容易出错,要注意