J - Fire! UVA
题目描述
乔在迷宫中工作。不幸的是,迷宫的一部分着火了,迷宫的主人没有制定火灾的逃跑计划。请帮助乔逃离迷宫。根据乔在迷宫中的位置以及迷宫的哪个方块着火,你必须确定火焰烧到他之前,乔是否可以离开迷宫,如果能离开他能跑多快。
乔和火每分钟移动一个方格,上、下、左、右,四个方向中的一个。火势向四个方向同时蔓延。乔可以从迷宫的任何一个边界逃离迷宫。无论是乔还是火都不会到达有墙的位置。
输入
第一行输入包含一个整数,即测试次数
每个测试用例的第一行包含两个
整数R和C,用空格分隔,1≤R,C≤1000
下面R行中,每一行都包含C个字符,以及每个字符是以下之一:
# 代表墙
. 代表空地,火和乔是可通行的
J 乔在迷宫中最初的位置,火和乔是可通行的
F 代表火
在每组测试中只有一个J
输出
对于每个测试用例,如果在火蔓延的时候烧到了乔,则乔无法逃出迷宫,输出'IMPOSSIBLE'如果乔能逃出迷宫,则输出乔最快可以在几分钟内安全逃出迷宫,每组输出占一行
样例输入
2
4 4
####
#JF#
#..#
#..#
3 3
###
#J.
#.F
样例输出
3
IMPOSSIBLE
思路:两次bfs,第一个bfs求出火蔓延到每个地方所需的最小时间。第二个bfs求Joe在火烧的同时(到达某一位置时火烧到的时间一定要比其大)是否可以到达边界·,以及逃出迷宫的时间。
注意:起火点不只一个。
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<queue>
using namespace std;
const int maxn=1005;
int vis[maxn][maxn];
int vis2[maxn][maxn];
char e[maxn][maxn];
int R,C;
int X[5]= {0,1,-1,0,0};
int Y[5]= {0,0,0,1,-1};
struct node
{
int x;
int y;
};
queue<node>q;
void firebfs()
{
for(int i=1; i<=R; i++)
for(int j=1; j<=C; j++)
{
if(e[i][j]=='F')///找到每一个起火点,并且将其入队列
{
vis[i][j]=0;
node p;
p.x=i;
p.y=j;
q.push(p);
}
}
while(!q.empty())
{
node head=q.front();
q.pop();
for(int i=1; i<5; i++)
{
int xx=head.x+X[i];
int yy=head.y+Y[i];
if(xx>=1&&xx<=R&&yy>=1&&yy<=C&&vis[xx][yy]==-1&&e[xx][yy]!='#')///范围以及可走的条件
{
vis[xx][yy]=vis[head.x][head.y]+1;///vis数组表示到达每一个点所需最短时间
node tmp;
tmp.x=xx;
tmp.y=yy;
q.push(tmp);
}
}
}
}
int joebfs(int x,int y)
{
while(!q.empty())
q.pop();
vis2[x][y]=0;
node p;
p.x=x;
p.y=y;
q.push(p);
while(!q.empty())
{
node head=q.front();
q.pop();
if(head.x==1||head.y==1||head.x==R||head.y==C) ///到达边界时,逃脱成功
return vis2[head.x][head.y]+1; ///从边界逃离需要+1分钟
for(int i=1; i<5; i++)
{
int xx=head.x+X[i];
int yy=head.y+Y[i];
if(xx>=1&&xx<=R&&yy>=1&&yy<=C&&vis2[xx][yy]==-1&&e[xx][yy]!='#')
{
vis2[xx][yy]=vis2[head.x][head.y]+1;
if(vis2[xx][yy]>=vis[xx][yy]&&vis[xx][yy]!=-1)///人到达该点的时间要晚于火到达的,且是火能到达的。
continue;
node tmp;
tmp.x=xx;
tmp.y=yy;
q.push(tmp);
}
}
}
return -1;
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
scanf("%d %d",&R,&C);
int jx,jy,fx,fy;
memset(vis,-1,sizeof(vis));
memset(vis2,-1,sizeof(vis2));
while(!q.empty())
q.pop();
for(int i=1; i<=R; i++)
for(int j=1; j<=C; j++)
cin>>e[i][j];
for(int i=1; i<=R; i++)
for(int j=1; j<=C; j++)
{
if(e[i][j]=='J')
{
jx=i;
jy=j;
}
}
firebfs();
int ans=joebfs(jx,jy);
if(ans==-1)
printf("IMPOSSIBLE\n");
else
printf("%d\n",ans);
}
return 0;
}