【题目】https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=2671
【题意】#是墙,J是人,F是火,火每1秒会向四周蔓延1格,问J最快能在几秒跑出图外,不能则输出IMPOSSIBLE
【思路】一开始思路是用每个F跑BFS更新所有点的最早着火时间,再从J跑BFS看能不能跑出去。然而T了...其实可以将所有的F一次性入队,跑一次BFS就行了,每个F一开始一定是最优的更新。
【代码】
#include<bits/stdc++.h>
#define fuck(x) std::cout<<"["<<#x<<"->"<<x<<"]"<<endl;
using namespace std;
typedef long long ll;
const int M=2e5+5;
const int inf=1e9+5;
int to[4][2]= {1,0,0,1,0,-1,-1,0};
char mp[1005][1005];
int fire[1005][1005];
int vis[1005][1005];
int n,m;
int jx,jy;
int ans;
struct node
{
int x,y,step;
};
queue<node>q;
void bfsf()
{
node t;
while(!q.empty())
{
t=q.front();
q.pop();
fire[t.x][t.y]=min(fire[t.x][t.y],t.step);
for(int i=0; i<4; i++)
{
if(t.x+to[i][0]<0||t.x+to[i][0]>=n||t.y+to[i][1]<0||t.y+to[i][1]>=m)
continue;
if(mp[t.x+to[i][0]][t.y+to[i][1]]=='#')
continue;
if(vis[t.x+to[i][0]][t.y+to[i][1]]==1)
continue;
vis[t.x+to[i][0]][t.y+to[i][1]]=1;
q.push({t.x+to[i][0],t.y+to[i][1],t.step+1});
}
}
}
void bfsj(int x,int y)
{
while(!q.empty())
q.pop();
node t{x,y,0};
vis[x][y]=1;
q.push(t);
while(!q.empty())
{
t=q.front();
q.pop();
if(t.x==0||t.y==0||t.x==n-1||t.y==m-1)
{
// fuck(t.step);
// fuck(t.x);
// fuck(t.y);
ans=min(ans,t.step+1);
}
for(int i=0; i<4; i++)
{
if(t.x+to[i][0]<0||t.x+to[i][0]>=n||t.y+to[i][1]<0||t.y+to[i][1]>=m)
continue;
if(mp[t.x+to[i][0]][t.y+to[i][1]]=='#')
continue;
if(t.step+1>=fire[t.x+to[i][0]][t.y+to[i][1]])
continue;
if(vis[t.x+to[i][0]][t.y+to[i][1]]==1)
continue;
vis[t.x+to[i][0]][t.y+to[i][1]]=1;
q.push({t.x+to[i][0],t.y+to[i][1],t.step+1});
}
}
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
while(!q.empty())
q.pop();
ans=inf;
fill(fire[0],fire[0]+1005*1005,inf);
scanf("%d%d",&n,&m);
for(int i=0; i<n; i++)
{
scanf("%s",mp[i]);
for(int j=0; j<m; j++)
{
if(mp[i][j]=='J')
jx=i,jy=j;
}
}
for(int i=0; i<n; i++)
{
for(int j=0; j<m; j++)
{
if(mp[i][j]=='F')
{
q.push({i,j,0});
}
}
}
memset(vis,0,sizeof(vis));
bfsf();
memset(vis,0,sizeof(vis));
bfsj(jx,jy);
if(ans!=inf)
printf("%d\n",ans);
else
printf("IMPOSSIBLE\n");
}
return 0;
}