题目链接:【UVA 11624】
n*m的迷宫是由.跟#组成的,.表示这是路,#表示这是墙,一个人在迷宫里面,迷宫着火了,J表示这个人在迷宫中的位置,F表示着火的地方,J想逃出来,每一分钟,J只能往前后左右四个方向走,但是火却能同时往四个方向蔓延,问J能不能顺利逃出迷宫,如果能,输出逃出迷宫的最少时间,如果不能,输出IMPOSSIBLE
这个题目有点坑,迷宫中J这个位置有且仅有一个,但是F可以不存在
先一次bfs,处理出每一小格着火时的时间,用f[i][j]=x表示ij这个位置在第x分钟的时候着火了
第二次bfs,J在ij这个位置时用了y分钟,如果y<f[i][j],那这个位置就是安全的,否则就会被烧死
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <string>
#include <queue>
using namespace std;
int t, n, m;
char str[1010][1010];
struct node
{
int x, y, step;
}s, e;
int vis[1010][1010], fire[1010][1010];
int f[4][2] = {0,1,1,0,0,-1,-1,0}, ans;
bool isok(int x, int y)
{//只要不是#的都能被烧到,J在的位置也能烧到,所以判断条件是str[x][y]!='#'
if(x>=1 &&x<=n&& y>=1 &&y<=m && str[x][y]!='#') return true;
return false;
}
void bfsfire()
{
memset(fire, -1, sizeof(fire));
queue<node>q;
for(int i=1; i<=n; i++)
for(int j=1; j<=m; j++)
if(str[i][j]=='F')
{
s.x=i, s.y=j, s.step=0;
q.push(s);
fire[i][j]=0;
}
while(!q.empty())
{
s = q.front(), q.pop();
for(int i=0; i<4; i++)
{
e = s;
e.x+=f[i][0], e.y+=f[i][1], e.step++;
if(isok(e.x, e.y)&&fire[e.x][e.y]==-1)
{
fire[e.x][e.y] = e.step;
q.push(e);
}
}
}
}
int bfsans()
{
memset(vis, -1, sizeof(vis));
queue<node>q;
for(int i=1; i<=n; i++)
for(int j=1; j<=m; j++)
if(str[i][j]=='J')
{
s.x=i, s.y=j, s.step=0;
q.push(s);
vis[i][j] = 1;
}
while(!q.empty())
{
s = q.front(), q.pop();
if(s.x==1||s.x==n||s.y==1||s.y==m) return s.step+1;
for(int i=0; i<4; i++)
{
e = s;
e.x += f[i][0];
e.y += f[i][1];
e.step++;
if(fire[e.x][e.y]!=-1 && fire[e.x][e.y]<=e.step) continue;
if(isok(e.x, e.y)&&vis[e.x][e.y]==-1)
{
vis[e.x][e.y]=1;
q.push(e);
}
}
}
return -1;
}
int main()
{
cin>>t;
while(t--)
{
cin>>n>>m;
for(int i=1; i<=n; i++) scanf("%s", str[i]+1);
bfsfire();
ans = bfsans();
if(ans==-1) printf("IMPOSSIBLE\n");
else printf("%d\n", ans);
}
return 0;
}