思路
人的起点只有一个,但火的起点可能有多个所以先将火的起点压入第一个队列,让他们同时 bfs 先到达的点即为最小步数(存到 s1[ ][ ] 数组中 ),只要人到达该点的步数比s1中该点的小,人就能到达该点。
一开始每搜到一个起火点就BFS一次,而且每次还要比较这一次bfs中火到达该点的步数与上一次bfs中火到达该点的步数的大小,取最小值。结果 超时了。。。
#include<iostream>
#include<cstdio>
#include<queue>
#include<cstring>
#define inf 0x3f3f3f3f
using namespace std;
bool v[1010][1010]; //标记数组
int s1[1010][1010]; //存储火到达 i,j点的最小步数
char s[1010][1010];
int r,c;
int a[4][2]={
1,0,
-1,0,
0,1,
0,-1
};
struct node
{
int x,y;
int k;
};
queue<node>p;
void fbfs()
{
node w,h;
while(!p.empty())
{
w=p.front();
p.pop();
for(int i=0;i<4;i++)
{
h.x=w.x+a[i][0];
h.y=w.y+a[i][1];
if(h.x>=0&&h.x<r && h.y>=0&&h.y<c && s[h.x][h.y]!='#' && !v[h.x][h.y])
{
h.k=w.k+1;
s1[h.x][h.y]=h.k;
v[h.x][h.y]=1;
p.push(h);
}
}
}
}
int pbfs(int x1,int y1)
{
for(int i=0;i<r;i++)
{
for(int j=0;j<c;j++)
v[i][j]=0;
}
queue<node>q;
node w,h;
w.x=x1;
w.y=y1;
w.k=0;
q.push(w);
v[x1][y1]=1;
while(!q.empty())
{
w=q.front();
q.pop();
if(w.x==0 || w.x==r-1 ||w.y==0 || w.y==c-1)
return w.k+1;
for(int i=0;i<4;i++)
{
h.x=w.x+a[i][0];
h.y=w.y+a[i][1];
if(h.x>=0&&h.x<r && h.y>=0&&h.y<c && s[h.x][h.y]=='.' && !v[h.x][h.y] && (w.k+1)<s1[h.x][h.y]) //因为 h.k 还没加一 所以用 w.k+1代替人到达该点的步数
{
h.k=w.k+1;
v[h.x][h.y]=1;
q.push(h);
}
}
}
return -1;
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
int a,b;
node w;
scanf("%d%d",&r,&c);
for(int i=0;i<r;i++)
{
scanf("%s",s[i]);
for(int j=0;j<c;j++)
{
v[i][j]=0;
s1[i][j]=inf;
if(s[i][j]=='J')
{
a=i;
b=j;
}
if(s[i][j]=='F')
{
w.x=i;
w.y=j;
w.k=0;
v[i][j]=1;
s1[i][j]=0;
p.push(w);
}
}
}
fbfs();
int n=pbfs(a,b);
if(n==-1)
printf("IMPOSSIBLE\n");
else
printf("%d\n",n);
}
return 0;
}
一个BFS也可以。。。