相信大家已经读过题目了,我就搬一下洛谷的翻译:
题目大意 你的任务是帮助Joe走出一个大火蔓延的迷宫。Joe每分钟可以走到上下左右4个方向的相邻格子之一,而所有着火的格子都会四周蔓延(即如果某个空格子与着火格子有公共边,则下一分钟这个空格子将着火)。迷宫中有一些障碍格,Joe和火都无法进入。当Joe走到一个迷宫的边界格子时,我们认为他已经出了迷宫。
输入数据 第一行为数据组数T。每一组测试数据格式如下: 第一行为两个整数R和C(1<=R,C<=1000)。以下R行每行有C个字符,即迷宫,其中“#”表示墙和障碍物,“.”表示空地,“J”是joe的初始位置(也就是空地),”F”是着火格子。每组数据的迷宫中恰好有一个格是”J”。
输出数据 对于每组测试数据,如无法走出迷宫,则输出IMPOSSIBLE,否则输出走出迷宫的最短时间(单位:分钟)。

输入

2
4 4
####
#JF#
#..#
#..#
3 3
###
#J.
#.F

输出

3
IMPOSSIBLE

题解:首先要注意火是不止一个的,我们分开设置两个搜索,一个搜索火到每个位置的时间,另一个搜索杰克走的路径,如果火比杰克提前到那个位置,杰克就不可以走那个位置。
本人因没有设置火到不了的地方为极大值wa了九发。

#pragma GCC optimize(3,"Ofast","inline")
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <math.h>
#include <string>
#include <list>
#include <set>
#include <map>
#include <queue>
#include <stack>
#include <algorithm>
#define maxn 1000000
//#define true false
//#define false true
const int MaxN=0x3f3f3f3f;
const int MinN=0xc0c0c00c;
const double pi=acos(-1);
typedef long long ll;
const int mod=1e9+7;
using namespace std;
int n,m;
char a[1010][1010];
int dx[4]={0,0,1,-1};
int dy[4]={1,-1,0,0};
bool visited[1010][1010];
struct wazxy{
    int x,y;
    int steps;
}temp,node;
int times[1010][1010];  //记录火的出现次数
queue <wazxy> fire,jack;

int ans;

void bfs_fire(){
    for(int i=1;i<=n;i++)    //把火挨着放进队列
        for(int f=1;f<=m;f++){
            if(a[i][f]=='F'){
                temp.x=i,temp.y=f,temp.steps=0;
                visited[i][f]=false;
                times[i][f]=0;
                fire.push(temp);
            }
        }
    while(!fire.empty()){    //开始搜索,标记火什么时候出现在什么位置
        node=fire.front();
        times[node.x][node.y]=node.steps;
        fire.pop();
        for(int i=0;i<4;i++){
            if(visited[node.x+dx[i]][node.y+dy[i]]&&((a[node.x+dx[i]][node.y+dy[i]]=='J')||(a[node.x+dx[i]][node.y+dy[i]]=='.'))){
                 visited[node.x+dx[i]][node.y+dy[i]]=false;
                 temp.x=node.x+dx[i],temp.y=node.y+dy[i],temp.steps=node.steps+1;
                 fire.push(temp);
            }
        }
    }
    return ;
}

void bfs_jack(int x,int y){
    node.steps=0,node.x=x,node.y=y;
    jack.push(node);
    while(!jack.empty()){
        temp=jack.front();
        jack.pop();
        if(temp.x>n||temp.x<1||temp.y>m||temp.y<1){  //我的判断依据是他超出地图即为跑出去,因为地图是从1开始所以不会re
            ans=temp.steps;
            return ;
        }
        if(times[temp.x][temp.y]<=temp.steps)  continue;   //这一点千万注意,如果火比jack早到了这一点,就把这一点作废
        for(int i=0;i<4;i++){
            if(visited[temp.x+dx[i]][temp.y+dy[i]]&&a[temp.x+dx[i]][temp.y+dy[i]]!='#'){
                visited[temp.x+dx[i]][temp.y+dy[i]]=false;
                node.x=temp.x+dx[i],node.y=temp.y+dy[i],node.steps=temp.steps+1;
                jack.push(node);
            }
        }
    }
    return ;
}

int main()
{
    int t;
    //freopen("in.txt","r",stdin);
    cin>>t;
    while(t--){
        while(!jack.empty()) jack.pop();   //不要忘记清空队列
        while(!fire.empty()) fire.pop();
        cin>>n>>m;
        for(int i=0;i<1010;i++){
            for(int f=0;f<1010;f++){   //赋初值没有到达的地方附上极大值
                times[i][f]=MaxN;  
            }
        }
        int x,y;
        getchar();
        memset(visited,true,sizeof(visited));
        memset(a,0,sizeof(a));
        for(int i=1;i<=n;i++){
            scanf("%s",a[i]+1);
        }
// for(int i=1;i<=n;i++){
// for(int f=1;f<=m;f++)
// cout<<a[i][f]<<" ";
// cout<<endl;
// }

        bfs_fire();
        for(int i=1;i<=n;i++){
            for(int f=1;f<=m;f++){
                if(a[i][f]=='J'){
                    x=i,y=f;
                    break;
                }
            }
        }
        ans=-1;
        memset(visited,true,sizeof(visited));
        bfs_jack(x,y);
        if(ans==-1) cout<<"IMPOSSIBLE"<<endl;
        else  cout<<ans<<endl;
    }
    return 0;
}