這道題沒什麼好說的,一個最短路徑的題,用寬搜。但是要注意的是,這道題是兩個寬搜,先算火(有多個火!)到每個點的距離,然後人就必須在火到那個點之前到達那個點,不然人(只有一個人)就要死了
#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();
}
}