题意:
Joe在迷宫里(咱也不知道他为啥去迷宫,咱也不敢问啊),然后呢还有火。Joe想逃出去,要不就被火烧到了。每个时刻,火都会向四周蔓延,那么Joe能不能逃出去,能输出最少的时间,不能就gg了,输出IMPOSSIBLE。
注意题目中有一句话:There will be exactlu one J int each test case.
就是说只有一个Joe,那么火呢?肯定是多个啊。(坑)
思路:
先把每个时刻的火bfs处理一下,然后在bfs一下Joe的路径能不能出去。到边界就出去了。
代码如下:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<stack>
#include<queue>
#include<set>
#include<algorithm>
#define sc(x) scanf("%d",&x)
#define scc(x,y) scanf("%d%d",&x,&y)
#define scll(x) scanf("%lld",&x)
#define mem(x,a) memset(x,a,sizeof x)
#define ll long long
#define INF 0x3f3f3f3f
using namespace std;
const int maxn = 1500;
char mp[maxn][maxn];
int fire_time[maxn][maxn]; // 记录每个时刻的火
bool vis[maxn][maxn];
int dir[][2]={0,1,1,0,0,-1,-1,0};
int n,m;
typedef pair<int,int> PII; // 由于火源不止一个,那么需要保存每个火源
queue<PII> Qfire; // 把火源直接放进队列bfs就OK了
struct node{
int x,y;
int v;
};
void fire_bfs(){
mem(vis,0);
while(!Qfire.empty()){
PII f = Qfire.front();
Qfire.pop();
int x = f.first;
int y = f.second;
vis[x][y] = 1;
for(int i=0;i<4;i++){
int xx = x+dir[i][0];
int yy = y+dir[i][1];
if(xx>=0 && xx<n && yy>=0 && yy<m && !vis[xx][yy] && mp[xx][yy]!='#'){
vis[xx][yy]=1;
fire_time[xx][yy]=fire_time[x][y]+1;
Qfire.push(PII(xx,yy));
}
}
}
}
void joe_bfs(int x,int y){
mem(vis,0);
queue<node> Q;
node t;
t.x = x;
t.y = y;
t.v = 1;
vis[x][y]=1;
Q.push(t);
while(!Q.empty()){
node f = Q.front();
Q.pop();
//cout<<f.x<<"----"<<f.y<<endl;
if(f.x+1==n || f.y+1==m || f.x==0 || f.y==0){
printf("%d\n",f.v);
return ;
}
node tmp;
for(int i=0;i<4;i++){
int xx = f.x+dir[i][0];
int yy = f.y+dir[i][1];
if(xx>=0 && xx<n && yy>=0 && yy<m && !vis[xx][yy] && mp[xx][yy]=='.' && fire_time[xx][yy]>f.v+1){
// fire_time[xx][yy]>f.v+1下一次肯定是去到比自己大至少2的时间点,才不会被烧
// 例如此时人的时间为1,则下一步人的时间是2,没问题吧,那么人不能去一个时间点小于等于2的带,因为那个点一定是火
vis[xx][yy]=1;
tmp.x = xx,tmp.y = yy,tmp.v = f.v+1;
Q.push(tmp);
}
}
}
printf("IMPOSSIBLE\n");
}
int main(){
int t;sc(t);
int jx,jy,fx,fy;
while(t--){
mem(mp,0);
mem(fire_time,INF);
scc(n,m);
for(int i=0;i<n;i++){
getchar();
for(int j=0;j<m;j++){
mp[i][j] = getchar();
if(mp[i][j]=='J'){ // 人
jx=i,jy=j;
}
if(mp[i][j]=='F'){ // 火
//fx=i,fy=j;
Qfire.push(PII(i,j)); //多个火源、、坑老子啊ToT
fire_time[i][j]=1;
}
}
}
fire_bfs();
// for(int i=0;i<n;i++){ //看看处理完的火的情况
// for(int j=0;j<m;j++){
// cout<<fire_time[i][j];
// }
// cout<<endl;
// }
joe_bfs(jx,jy);
}
}
总结:
虽然ac了但是有一点不是太明白,如果一个火源很好理解,处理完就好了,那么多个火源,在处理第二个火源时是否会存在一个点p,这个点通过A火源是在第三个时刻到达的,而还可以通过B火源第二个时刻到达,但是A火源首先遍历会让B火源无法访问点p.那么人是否有可能在第二个时刻到了p点,其实如果从B火源燃烧过来这个点p也正好着火,是不能到达的。但是由于我们先处理了A火源,导致p点在第三时刻才有火,反而可以到达了。是不是有点小瑕疵。也可能是我哪里想的不对。望大家指正。感谢!