题目链接:https://cn.vjudge.net/contest/219479#problem/J
题目大意:一个人要从火场里出来,不知道多少火的起始点,或可以蔓延,人不能走墙,不能走火,问人是否能出来,最少多久
解题思路:bfs,多个同时bfs,用两个数组分别标记已走过路程,人和火分别讨论,因为人不能走人已经走过的,也不能走火已经走过的,但是火可以走人已经走过的,但火不能走火走过的。
#include <iostream>
#include <cstdio>
#include <queue>
#include <cstring>
using namespace std;
int r,c;
struct node
{
int x,y,time,no;
}fire[1000009];
char mp[1009][1009];
void bfs(int jx,int jy,int I)
{
int i;
bool b[2][1009][1009];
memset(b,0,sizeof(b));
queue<struct node> q;
struct node t,tt;
for(i=1;i<=I;i++)
{
t=fire[i];
b[0][t.y][t.x]=true;
q.push(t);
}
t.y=jy;
t.x=jx;
t.time=0;
t.no=1;
q.push(t);
b[1][t.y][t.x]=true;
int d[4][2]={1,0,-1,0,0,1,0,-1};
bool flag=false;
while(!q.empty())
{
t=q.front();
if(t.no==1&&(t.y==r||t.y==1||t.x==c||t.x==1))
{
flag=true;
break;
}
q.pop();
for(i=0;i<=3;i++)
{
tt.y=t.y+d[i][0];
tt.x=t.x+d[i][1];
tt.time=t.time+1;
tt.no=t.no;
if(tt.no==1)
{
if(b[1][tt.y][tt.x]==0&&b[0][tt.y][tt.x]==0&&mp[tt.y][tt.x]=='.')
{
q.push(tt);
b[tt.no][tt.y][tt.x]=true;
}
}
if(tt.no==0)
{
if(b[0][tt.y][tt.x]==0&&mp[tt.y][tt.x]=='.'&&tt.y<=r&&tt.y>=1&&tt.x<=c&&tt.x>=1)
{
q.push(tt);
b[tt.no][tt.y][tt.x]=true;
}
}
}
}
if(flag)
{
printf("%d\n",t.time+1);
}
else
{
printf("IMPOSSIBLE\n");
}
}
int main()
{
int t,i,j,jx,jy;
scanf("%d",&t);
while(t--)
{
scanf("%d %d",&r,&c);
getchar();
int I=0;
for(i=1;i<=r;i++)
{
for(j=1;j<=c;j++)
{
scanf("%c",&mp[i][j]);
if(mp[i][j]=='J')
{
jx=j;
jy=i;
}
else if(mp[i][j]=='F')
{
fire[++I].y=i;
fire[I].x=j;
fire[I].time=0;
fire[I].no=0;
}
}
getchar();
}
bfs(jx,jy,I);
}
return 0;
}