题目大意:有火,火会扩散,找出逃出迷宫的最短路
两次Bfs,一次标记火的扩散,一次标记人的;
人不会被火烧的判定条件是其步数小于火的步数。
最后在迷宫的四条边界上找最小的ans
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<queue>
#include<vector>
#include<algorithm>
using namespace std;
const int INF=1000000000+10;
const int maxn=1000+10;
int R,C,ans;
char maze[maxn][maxn];
int xx[4]={0,0,1,-1};
int yy[4]={1,-1,0,0};
int vis[maxn][maxn][2],d[maxn][maxn][2];
struct Node{
int x,y;
Node(int x,int y):x(x),y(y){}
};
queue<Node>Q;
bool check(int r,int c,int kind){
if(r<0||r>=R ||c<0||c>=C)return false;
if(vis[r][c][kind]==1)return false;
return true;
}
void bfs(int kind){
while(!Q.empty()){
Node now=Q.front();Q.pop();
int r=now.x,c=now.y;
for(int i=0;i<4;i++){
int rr=r+xx[i],cc=c+yy[i];
if(!check(rr,cc,kind))continue;
vis[rr][cc][kind]=1;
d[rr][cc][kind]=d[r][c][kind]+1;
Q.push(Node(rr,cc));
}
}
}
void find(int r,int c){
if(!vis[r][c][0])return;
if(!vis[r][c][1] || d[r][c][0]<d[r][c][1])ans=min(ans,d[r][c][0]+1);
}
int main(){
int T;
scanf("%d",&T);
while(T--){
memset(vis,0,sizeof(vis));
memset(d,0,sizeof(d));
vector<Node>fire;
scanf("%d%d",&R,&C);
for(int i=0;i<R;i++){
scanf("%s",maze[i]);
for(int j=0;j<C;j++){
if(maze[i][j]=='#'){vis[i][j][0]=vis[i][j][1]=1;}
else if(maze[i][j]=='J')Q.push(Node(i,j));
else if(maze[i][j]=='F')fire.push_back(Node(i,j));
}
}
Node node=Q.front();
vis[node.x][node.y][0]=1;
bfs(0);
for(int i=0;i<fire.size();i++){
vis[fire[i].x][fire[i].y][1] = 1;
Q.push(fire[i]) ;
}
bfs(1);
ans=INF;
for(int i=0;i<R;i++){find(i,0);find(i,C-1);}
for(int i=0;i<C;i++){find(0,i);find(R-1,i);}
if(ans==INF)printf("IMPOSSIBLE\n");
else printf("%d\n",ans);
}
return 0;
}