Fire! UVA - 11624
题面:点链接看
题意:一个平面迷宫中有一个人,迷宫中有些点起火了,火和人每个单位时间只能向相邻的格子移动,
其中有一些空间被墙壁占据,问这个人在不背或烧到的情况下,离开迷宫的最快时间。要注意火可能不止一处,但是人只有一个
思路:
两次BFS,首先把开始的F(火)入队,然后进行BFS 并用times数组记录到达每个位置的时间(初始化为INF,不可达则为INF),然后进行逃跑路线的BFS,当满足基本条件(不越界,未被访问),再满足到达某点时间小于该点的times,则说明在火到达之前,到此位置。如此进行,知道到达边界或者队列为空也没到达(IMPOSSIBLE)。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <queue>
using namespace std;
const int INF=0x3f3f3f3f;
const int maxn=1005;
int T;
int n,m;
int si,sj;
int ans;
char s[maxn][maxn];
int timee[maxn][maxn];
bool vis[maxn][maxn];
int dx[]={0,0,1,-1};
int dy[]={1,-1,0,0};
struct Node
{
int x,y;
int step;
};
Node now,temp,nex;
queue<Node>q;
void init()
{
while(!q.empty())
q.pop();
memset(vis,false,sizeof(vis));
memset(timee,INF,sizeof(timee));
ans=0;
}
void prebfs()
{
while(!q.empty())
{
temp=q.front();
q.pop();
for(int i=0;i<4;i++)
{
nex.x=temp.x+dx[i];
nex.y=temp.y+dy[i];
if(vis[nex.x][nex.y]==false&&s[nex.x][nex.y]=='.')
{
vis[nex.x][nex.y]=true;
nex.step=temp.step+1;
timee[nex.x][nex.y]=nex.step;
q.push(nex);
}
}
}
}
bool bfs()
{
memset(vis,false,sizeof(vis));
queue<Node>qq;
now.x=si;now.y=sj;now.step=0;
vis[si][sj]=true;
qq.push(now);
while(!qq.empty())
{
temp=qq.front();
qq.pop();
for(int i=0;i<4;i++)
{
nex.x=temp.x+dx[i];
nex.y=temp.y+dy[i];
if(nex.x<1||nex.y<1||nex.x>n||nex.y>m)
{
ans=temp.step+1;
return true;
}
if(vis[nex.x][nex.y]==false&&s[nex.x][nex.y]=='.'&&temp.step+1<timee[nex.x][nex.y])
{
vis[nex.x][nex.y]=true;
nex.step=temp.step+1;
qq.push(nex);
}
}
}
return false;
}
int main()
{
scanf("%d",&T);
while(T--)
{
init();
scanf("%d %d",&n,&m);
for(int i=1;i<=n;i++)
scanf("%s",s[i]+1);
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
if(s[i][j]=='F')
{
now.x=i;now.y=j;
now.step=0;
vis[i][j]=true;
q.push(now);
}
if(s[i][j]=='J')
{
si=i;sj=j;
}
}
}
prebfs();
if(bfs())
printf("%d
",ans);
else
printf("IMPOSSIBLE
");
}
return 0;
}