https://cn.vjudge.net/problem/UVA-11624
先对火做一次bfs处理出经过的所有点的时间,再对人bfs,满足时间小于火的
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#define maxn 1500
#define inf 0x3f3f3f3f
using namespace std;
int sx,sy;
struct node
{
int x,y,time;
};
int r,c;
char mp[maxn][maxn];
int dx[4]={1,-1,0,0};
int dy[4]={0,0,1,-1};
int vis[maxn][maxn];
int f[maxn][maxn];
queue<node>qf;
void fbfs()
{
node u,v;
while(!qf.empty())
{
u=qf.front();
qf.pop();
for(int i=0;i<4;i++)
{
v.x=u.x+dx[i];
v.y=u.y+dy[i];
v.time=u.time+1;
if(mp[v.x][v.y]!='#'&&!vis[v.x][v.y]&&v.x>=0&&v.x<r&&v.y>=0&&v.y<c)
{
qf.push(v);
vis[v.x][v.y]=1;
if(v.time<f[v.x][v.y])
f[v.x][v.y]=v.time;
}
}
}
}
int jbfs()
{queue<node>q;
memset(vis,0,sizeof(vis));
node u,v,w;
vis[sx][sy]=1;
u.x=sx;
u.y=sy;
u.time=0;
q.push(u);
while(!q.empty())
{
v=q.front();
q.pop();
for(int i=0;i<4;i++)
{
w.x=v.x+dx[i];
w.y=v.y+dy[i];
w.time=v.time+1;
if(w.x>=0&&w.x<r&&w.y>=0&&w.y<c)
{if(mp[w.x][w.y]!='#'&&!vis[w.x][w.y]&&w.time<f[w.x][w.y])
{
q.push(w);
vis[w.x][w.y]=1;
}
}
else
{
return w.time;
}
}
}
return -1;
}
int main()
{
int t;
scanf("%d", &t);
while(t--)
{
scanf("%d%d", &r, &c);
for(int i = 0; i < r; i++)
scanf("%s", mp[i]);
for(int i = 0; i < r; i++)
for(int j = 0; j < c; j++)
f[i][j] = inf; //初始化时间
while(!qf.empty()) //清空队列
qf.pop();
struct node temp;
for(int i = 0; i < r; i++)
for(int j = 0; j < c; j++)
{
if(mp[i][j] == 'F')
{
temp.x = i;
temp.y = j;
temp.time = 0;
qf.push(temp); //每一个着火点入队
vis[i][j] = 1;
}
else if(mp[i][j] == 'J')
{
sx = i;
sy = j;
}
}
memset(vis, 0, sizeof(vis));
fbfs();
int cnt = jbfs();
if(cnt!=-1)
printf("%d\n", cnt);
else
printf("IMPOSSIBLE\n");
}
return 0;
}