题意
有一个 n ∗ m ( 1 ≤ n , m ≤ 1000 ) n*m(1\leq n,m\leq 1000) n∗m(1≤n,m≤1000)的网格,网格中有些地方是空地,有些地方是墙,有些地方是火。一个人从起点出发逃生,每分钟可以向上下左右四个方向移动 1 1 1格,火每分钟也会向上下左右四个方向蔓延 1 1 1格,人能够在不触碰到火的情况下跑到边界的空地就算逃生成功,判断人能否逃生成功以及逃生成功所需要的最短时间。
题解
两次
b
f
s
bfs
bfs
第一次对火进行
b
f
s
bfs
bfs,预处理得到所有位置被火蔓延到的最短时间。
第二次对人能够移动到的位置进行
b
f
s
bfs
bfs,不越界并且不是墙并且人到达的最短时间小于火蔓延到的最短时间即为合法位置。
#include<bits/stdc++.h>
#define LL long long
#define PII pair<int,int>
using namespace std;
const int maxn=1010,inf=1e9+10;
int T,n,m,book[maxn][maxn],dis[maxn][maxn],sx,sy,dir[4][2]={{0,1},{0,-1},{1,0},{-1,0}};
char s[maxn][maxn];
struct node{
int x,y,step;
node(int xx=0,int yy=0,int sstep=0):x(xx),y(yy),step(sstep){}
}t1,t2;
queue<node> q;
bool finish(node t){
if((t.x==0 || t.x==n-1 || t.y==0 || t.y==m-1) && (s[t.x][t.y]=='.') && t.step<dis[t.x][t.y]){
return true;
}
return false;
}
bool judge(node t){
if(t.x<0 || t.x>=n || t.y<0 || t.y>=m || book[t.x][t.y] || s[t.x][t.y]!='.' || t.step>=dis[t.x][t.y]){
return false;
}
return true;
}
void bfs1(){
while(!q.empty()){
t1=q.front();
q.pop();
for(int i=0;i<4;i++){
t2.x=t1.x+dir[i][0];
t2.y=t1.y+dir[i][1];
t2.step=t1.step+1;
if(s[t2.x][t2.y]=='.' && dis[t2.x][t2.y]==inf){
dis[t2.x][t2.y]=t2.step;
q.push(t2);
}
}
}
}
int bfs2(){
while(!q.empty()) q.pop();
t1=node(sx,sy,0);
book[sx][sy]=1;
if(finish(t1)) return t1.step;
q.push(t1);
while(!q.empty()){
t1=q.front();
q.pop();
for(int i=0;i<4;i++){
t2.x=t1.x+dir[i][0];
t2.y=t1.y+dir[i][1];
t2.step=t1.step+1;
if(judge(t2)){
book[t2.x][t2.y]=1;
if(finish(t2)) return t2.step;
q.push(t2);
}
}
}
return -1;
}
int main(){
scanf("%d",&T);
while(T--){
scanf("%d %d",&n,&m);
for(int i=0;i<n;i++) scanf("%s",s+i);
for(int i=0;i<n;i++){
for(int j=0;j<m;j++){
dis[i][j]=inf;
}
}
while(!q.empty()) q.pop();
for(int i=0;i<n;i++){
for(int j=0;j<m;j++){
book[i][j]=0;
if(s[i][j]=='J'){
sx=i;
sy=j;
s[i][j]='.';
}
if(s[i][j]=='F'){
dis[i][j]=0;
q.push(node(i,j,0));
}
}
}
bfs1();
int ans=bfs2();
if(ans!=-1) printf("%d\n",ans+1);
else printf("IMPOSSIBLE\n");
}
}