【题意】一个迷宫里面有两个人,一个是M,一个是G,里面还有两个鬼,给出这个迷宫的状态。现在M每一秒可以走3步,G每一秒只能走一步。鬼每一秒可以走两步,鬼走过的地方人不能走,不然会死的很惨。现在问你M和G能不能相遇?如果能的话,输出需要走的时间。不能的话,输出-1.

【分析&解题思路】题目给的迷宫是800*800,所以考虑一般的bfs是过不了的,这里才用双向的bfs。但是题目里面还是包含一个坑点的,也许是我代码太丑,觉得这是坑点。具体细节就见我的AC代码啦QAQ!

【AC代码】

#include <cstdio>
#include <cstring>
#include <stdlib.h>
#include <queue>
#include <iostream>
using namespace std;
const int maxn = 802;
int dir[4][2]={{0,1},{0,-1},{-1,0},{1,0}};
struct node{
    int x,y;
    node(){}
    node(int x,int y):x(x),y(y){}
};
int n,m;
char maze[maxn][maxn];
bool visit0[maxn][maxn];
bool visit1[maxn][maxn];
node ghost[2],st0,st1;
bool check(int x,int y){
    if(x>=0&&x<n&&y>=0&&y<m) return true;
    else return false;
}
bool validZ(int x,int y,int cost){
    if(2*cost<abs(x-ghost[0].x)+abs(y-ghost[0].y)&&2*cost<abs(x-ghost[1].x)+abs(y-ghost[1].y)) return true;
    else   return false;
}
int two_bfs(){
    int k,t=0,siz;
    node now;
    queue<node>Q0;
    queue<node>Q1;
    while(!Q0.empty()) Q0.pop();
    while(!Q1.empty()) Q1.pop();
    memset(visit0,false,sizeof(visit0));
    memset(visit1,false,sizeof(visit1));
    visit0[st0.x][st0.y]=true,visit1[st1.x][st1.y]=true;
    Q0.push(st0);
    Q1.push(st1);
    while(!Q0.empty()||!Q1.empty()){
        ++t;
        k=3;
        while((k--)){
            siz=Q0.size();
            while(siz--){
                now=Q0.front();
                Q0.pop();
                if(validZ(now.x,now.y,t)==false) continue;
                for(int i=0;i<4;i++){
                    int dx=now.x+dir[i][0];
                    int dy=now.y+dir[i][1];
//                    if(visit1[dx][dy]==true) return t;这里必须要先判断一下是否能走到这个点,因此不能写在这里,wo坑了好久
                    if(check(dx,dy)&&validZ(dx,dy,t)&&!visit0[dx][dy]&&maze[dx][dy]!='X'){
                        if(visit1[dx][dy]==true) return t;
                        visit0[dx][dy]=true;
                        Q0.push(node(dx,dy));
                    }
                }
            }
        }
        siz=Q1.size();
        while(siz--){
            now=Q1.front();
            Q1.pop();
            if(validZ(now.x,now.y,t)==false) continue;
            for(int i=0;i<4;i++){
                    int dx=now.x+dir[i][0];
                    int dy=now.y+dir[i][1];
//                    if(visit0[dx][dy]==true) return t;坑点之一
                    if(check(dx,dy)&&validZ(dx,dy,t)&&!visit1[dx][dy]&&maze[dx][dy]!='X'){
                        if(visit0[dx][dy]==true) return t;
                        visit1[dx][dy]=true;
                        Q1.push(node(dx,dy));
                    }
                }
        }
    }
    return -1;
}
int main(){
    int tt,k;
    scanf("%d",&tt);
    while(tt--){
        k=0;
        scanf("%d%d",&n,&m);
        for(int i=0; i<n; i++) scanf("%s",maze[i]);
        for(int i=0; i<n; i++){
            for(int j=0; j<m; j++){
                if(maze[i][j]=='Z'){
                    ghost[k++]=node(i,j);
                }else if(maze[i][j]=='M'){
                    st0=node(i,j);
                }else if(maze[i][j]=='G'){
                    st1=node(i,j);
                }
            }
        }
        int ans=two_bfs();
        printf("%d\n",ans);
    }
    return 0;
}