几个需要注意的地方:
①向左转我用d=(d-1)%4,这是错误的,当d=0时d会变成-1,应该用d=(d+3)%4才对。
②关于坐标方面的问题,我们在程序实现的时候更喜欢用行与列的概念,而在数学上我们更喜欢用x轴与y轴的概念。但是事实上行是对应y,列是对应x,如果不注意的话很容易就混用了,混用的话会且只会搞错方向。具体解决办法也很简单,把x与y或行与列互换一下即可。或者你干脆别用xy轴的概念就好了。
解法:
在普通的迷宫问题中,每一格只有一个状态。但是在此题中,每一格有多个状态(还要考虑颜色与方向)。
那就多记录每一个格子不同状态的最短距离,然后照常跑bfs即可。
当然你也可以理解成在四维空间上的bfs。
任何bfs的本质都是状态的bfs。其中涉及状态的定义以及状态的转移。
格子的bfs的本质当然也是状态的bfs。
迷宫问题可以说是bfs最好理解的实例了。
但如果你对bfs的理解只停留在迷宫问题上,那理解就未免太狭隘了。
代码
#include<bits/stdc++.h>
using namespace std;
const int maxn = 30;
const int inf = 0x3f3f3f3f;
int dy[4]={ 0, 1, 0,-1};
int dx[4]={-1, 0, 1, 0};
struct st
{
int x,y;
int c;
int d;
int t;
st(int x=0,int y=0,int c=0,int d=0,int t=0):x(x),y(y),c(c),d(d),t(t){}
st f()
{
return st(x+dx[d],y+dy[d],(c+1)%5,d,t+1);
}
st l()
{
return st(x,y,c,(d+3)%4,t+1);
}
st r()
{
return st(x,y,c,(d+1)%4,t+1);
}
};
st S,T;
int N,M;
char MAP[maxn][maxn];
int D[maxn][maxn][5][5];
int kase;
void Update(st now)
{
D[now.x][now.y][now.c][now.d]=now.t;
}
bool ok(st to)
{
bool OK=to.x>0&&to.x<=N&&to.y>0&&to.y<=M;
return OK&&MAP[to.x][to.y]!='#'&&to.t<D[to.x][to.y][to.c][to.d];
}
bool ed(st to)
{
return to.x==T.x&&to.y==T.y&&to.c==T.c;
}
int bfs()
{
memset(D,inf,sizeof(D));
queue<st>q;
q.push(S);
Update(S);
while(!q.empty())
{
st now=q.front();
q.pop();
for(int i=0;i<3;i++)
{
st to;
if(i==0) to=now.f();
else if(i==1) to=now.l();
else to=now.r();
if(ok(to))
{
if(ed(to)) return to.t;
Update(to);
q.push(to);
}
}
}
return -1;
}
int main()
{
while(scanf("%d %d",&N,&M)==2&&(N+M))
{
if(kase) puts("");
for(int i=1;i<=N;i++)
{
scanf("%s",MAP[i]+1);
for(int j=1;j<=M;j++)
{
if(MAP[i][j]=='S') S=st(i,j,0,0,0);
if(MAP[i][j]=='T') T=st(i,j,0,0,0);
}
}
int ans=bfs();
printf("Case #%d\n",++kase);
if(ans==-1) puts("destination not reachable");
else printf("minimum time = %d sec\n",ans);
}
return 0;
}