用数组维护可以走的方向和火移动的方向。
BFS: 可以将‘S’所在的地方扩散出去,如果是'#''F''S'就不能扩散,反之则可以,用队列维护边缘坐标。
记住:当边缘坐标被火吞没时,该坐标不能移动,这需要特别判定。
#include<iostream>
#include<algorithm>
#include<queue>
using namespace std;
#define MAXSIZE 50
char mat[MAXSIZE][MAXSIZE];
queue<pair<int,int>>fire;
queue<pair<int,int>>per;
int udlr[4][2]={{1,0},{-1,0},{0,1},{0,-1}};
int sur[8][2]={{1,0},{-1,0},{0,1},{0,-1},
{1,1},{-1,-1},{1,-1},{-1,1}};
bool run(pair<int,int> pos){
if(mat[pos.first][pos.second]=='*'){
return false;
}
for(int i=0;i<4;++i){
char* temp=&mat[pos.first+udlr[i][0]][pos.second+udlr[i][1]];
switch (*temp)
{
case '.':
*temp='S';
per.push({pos.first+udlr[i][0],pos.second+udlr[i][1]});
break;
case 'E':
return true;
}
}
return false;
}
bool isEndAndSpread(pair<int,int>pos){
for(int i=0;i<8;++i){
char* temp=&mat[pos.first+sur[i][0]][pos.second+sur[i][1]];
switch (*temp)
{
case '.':
case '#':
case 'S':
*temp='*';
fire.push({pos.first+sur[i][0],pos.second+sur[i][1]});
break;
case 'E':
return true;
}
}
return false;
}
void initializeEdge(int n,int m){
for(int i=0;i<=n+1;++i){
mat[i][0]=mat[i][m+1]='*';
}
for(int i=0;i<=m+1;++i){
mat[0][i]=mat[n+1][i]='*';
}
}
int gettime(){
int time=1;
while(!per.empty()){//people can go somewhere
int persize=per.size();
while(persize--){
if(run(per.front())){
return time;
}else{
per.pop();
}
}
int firesize=fire.size();
while(firesize--){
if(isEndAndSpread(fire.front())){
return -1;
}else{
fire.pop();
}
}
++time;
}
return -1;
}
int main(){
#ifdef LOCAL
freopen("in.txt","r",stdin);
freopen("out.txt","w",stdout);
#endif
int T;
cin>>T;
while(T--){
while(!fire.empty())fire.pop();
while(!per.empty())per.pop();
int n,m;
cin>>n>>m;
initializeEdge(n,m);
cin.get();
for(int in=1;in<=n;++in){
for(int im=1;im<=m;++im){
mat[in][im]=cin.get();
if(mat[in][im]=='S'){
per.push({in,im});
}else if(mat[in][im]=='*'){
fire.push({in,im});
}
}
cin.get();
}
int time=gettime();
if(time==-1){
cout<<"T_T"<<endl;
}else{
cout<<time<<endl;
}
}
}