#include<bits/stdc++.h>
#define debu
using namespace std;
const int INF=999999;
const int maxn=1e3+50;
const int dx[4]= {0,0,1,-1};
const int dy[4]= {1,-1,0,0};
struct point
{
int x,y,t;
point(int a=0,int b=0,int c=0):x(a),y(b),t(c) {}
};
int ans;
int n,m,stx,sty;
queue<point> q;
string st[maxn];
int vis[maxn][maxn];
int T[maxn][maxn];
void init()
{
memset(vis,0,sizeof(vis));
while(!q.empty()) q.pop();
}
int check1(int x,int y)
{
return x>=0&&x<n&&y>=0&&y<m&&!vis[x][y]&&st[x][y]!='#'&&st[x][y]!='F';
}
int check2(int x,int y)
{
return !vis[x][y]&&st[x][y]!='#';
}
int check(int x,int y)
{
return x<0||x>=n||y<0||y>=m;
}
void prepare()
{
while(!q.empty())
{
point u=q.front();
q.pop();vis[u.x][u.y]=0;
for(int i=0;i<4;i++)
{
int x=u.x+dx[i];
int y=u.y+dy[i];
if(check1(x,y))
{
if(T[x][y]>T[u.x][u.y]+1)
{
T[x][y]=T[u.x][u.y]+1;
if(!vis[x][y])
{
point v;
v.x=x;v.y=y;
v.t=u.t+1;
q.push(v);
vis[x][y]=1;
}
}
}
}
}
}
void solve()
{
ans=INF;
point u;
vis[stx][sty]=1;
q.push(point(stx,sty,0));
while(!q.empty())
{
point u=q.front();
q.pop();
for(int i=0; i<4; i++)
{
int x=u.x+dx[i];
int y=u.y+dy[i];
if(check2(x,y))
{
if(check(x,y))
{
ans=u.t+1;
return ;
}
if(T[x][y]>u.t+1)
{
point v;
v.x=x;
v.y=y;
vis[x][y]=1;
v.t=u.t+1;
q.push(v);
}
}
}
}
}
int main()
{
#ifdef debug
freopen("in.in","r",stdin);
#endif // debug
int t;
scanf("%d",&t);
while(t--)
{
init();
memset(T,127,sizeof(T));
scanf("%d%d",&n,&m);
for(int i=0; i<n; i++)
{
cin>>st[i];
for(int j=0; j<m; j++)
{
if(st[i][j]=='J')
{
stx=i;
sty=j;
}
if(st[i][j]=='F')
{
q.push(point(i,j,0));
T[i][j]=0;
}
}
}
prepare();
/*for(int i=0;i<n;i++)
{
for(int j=0;j<m;j++)
cout<<i<<" "<<j<<" "<<T[i][j]<<endl;
}*/
init();
solve();
if(ans!=INF) printf("%d\n",ans);
else printf("IMPOSSIBLE\n");
}
return 0;
}
题目地址:https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=2671
题解:求火到每个可达点的最小时间(即最短路),BFS扩展时加上判断当前时间与着火时间即可(now+1<t[x][y]时可行)。