这道题没什么好说的,一个最短路径的题,用宽搜。但是要注意的是,这道题是两个宽搜,先算火(有多个火!)到每个点的距离,然后人就必须在火到那个点之前到达那个点,不然人(只有一个人)就要死了
#include<iostream>
#include<cmath>
#include<queue>
#include<cstring>
#include<queue>
using namespace std;
const int maxn=1006;
const int inf=0x3f3f3f3f;
char a[maxn][maxn];
int man[maxn][maxn];
int fire[maxn][maxn];
int direction[4][2]={{0,1},{1,0},{-1,0},{0,-1}};
int line,column;
int start,start1;
struct wo{
int x;
int y;
};
queue<wo>p;
int makefire(){//着火
//while(p.size())p.pop()在main函数里面已经清空了;
while(p.size()){
wo help1;
help1=p.front();p.pop();
for(int i=0;i<4;i++){
int x1=help1.x+direction[i][0],y1=help1.y+direction[i][1];
if(x1<1||x1>line)continue;
if(y1<1||y1>column)continue;
if(a[x1][y1]=='#')continue;
if(fire[x1][y1]!=inf)continue;//没越出边界而且还不是墙且没走过才行
fire[x1][y1]=fire[help1.x][help1.y]+1;
wo help2;
help2.x=x1;help2.y=y1;
p.push(help2);
}
}
}
int run(){
while(p.size())p.pop();//清空
wo ps;ps.x=start;ps.y=start1;
p.push(ps);
while(p.size()){
ps=p.front();p.pop();
if(ps.x==1||ps.x==line||ps.y==1||ps.y==column){
//cout<<ps.x<<" "<<ps.y<<endl;
return man[ps.x][ps.y]+1;
}
for(int i=0;i<4;i++){
int x1=ps.x+direction[i][0],y1=ps.y+direction[i][1];
if(x1<1||x1>line)continue;
if(y1<1||y1>column)continue;
if(man[x1][y1]<=man[ps.x][ps.y]+1)continue;
if(a[x1][y1]=='#')continue;
if(fire[x1][y1]<=man[ps.x][ps.y]+1)continue;//当时那个点没着火且不是墙,没走过才行(重走你走过的点无聊吗?)
man[x1][y1]=man[ps.x][ps.y]+1;
wo help2;
help2.x=x1;help2.y=y1;
p.push(help2);
}
}
return -1;
}
int main(){
int t;
cin>>t;
while(t--){
memset(man,inf,sizeof(man));//初始化
memset(fire,inf,sizeof(fire));
cin>>line>>column;
wo help;
for(int i=1;i<=line;i++){
for(int j=1;j<=column;j++){
cin>>a[i][j];
if(a[i][j]=='J'){
start=i;start1=j;
man[start][start1]=0;
}
else if(a[i][j]=='F'){
help.x=i;help.y=j;
fire[i][j]=0;
p.push(help);//入队
}
}
}
makefire();//圣火
int ff=-1;
ff=run();
if(ff==-1)cout<<"IMPOSSIBLE"<<endl;跑不出去就只有乖乖等死了
else cout<<ff<<endl;
while(p.size())p.pop();
}
}