双向BFS板子题记录一下。
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <queue>
using namespace std;
typedef pair<int,int> P;
const int MAXN = 810;
char maze[MAXN][MAXN];
P Ghost[2],temp;
queue< P > qu[2];
int Bsx,Bsy,Gsx,Gsy; //男孩和女孩分别的开始位置
int n,m,step;
int vis[2][MAXN][MAXN];
//int dx[4][2] = {1,0,-1,0,0,1,0,-1};
int dx[4] = {-1,0,1,0},dy[4] = {0,1,0,-1};
void Input(){
scanf("%d %d",&n,&m);
for(int i = 0; i < n; i++)
scanf("%s",maze[i]);
int k = 0;
for(int i = 0; i < n; i++){
for(int j = 0; j < m; j++){
if(maze[i][j] == 'M'){ Bsx = i; Bsy = j;}
if(maze[i][j] == 'G') { Gsx = i; Gsy = j; }
if(maze[i][j] == 'Z'){
Ghost[k].first = i;
Ghost[k].second = j;
k++;
}
}
}
}
bool Check(P x){
if(x.first < 0 || x.second < 0 || x.first >= n || x.second >= m || maze[x.first][x.second] == 'X') return false;
if(abs(x.first - Ghost[0].first) + abs(x.second - Ghost[0].second) <= 2 * step ||
abs(x.first - Ghost[1].first) + abs(x.second - Ghost[1].second) <= 2 * step)
return false;
return true;
}
int BFS(int w){
P e1,e2;
//vis[w][e1.first][e1.second] = 1;
int len = qu[w].size();
while(len--){
e1 = qu[w].front(); qu[w].pop();
if(!Check(e1)) continue;
for(int i = 0; i < 4; i++){
e2.first = e1.first + dx[i];
e2.second = e1.second + dy[i];
if(!Check(e2)) continue;
if(!vis[w][e2.first][e2.second]){
if(vis[1 - w][e2.first][e2.second]) return 1;
vis[w][e2.first][e2.second] = 1;
qu[w].push(e2);
}
}
}
return 0;
}
int Solve(){
memset(vis,0,sizeof(vis));
while(!qu[0].empty()) qu[0].pop();
while(!qu[1].empty()) qu[1].pop();
temp.first = Bsx; temp.second = Bsy;
vis[0][Bsx][Bsy] = 1;
qu[0].push(temp);
temp.first = Gsx; temp.second = Gsy;
vis[1][Gsx][Gsy] = 1;
qu[1].push(temp);
step = 0;
while(!qu[0].empty() || !qu[1].empty()){
step++;
//男生走三步
if(BFS(0)) return step;
if(BFS(0)) return step;
if(BFS(0)) return step;
//女生走一步
if(BFS(1)) return step;
}
return -1;
}
int main(int argc, char const *argv[])
{
int t;
scanf("%d",&t);
while(t--){
Input();
printf("%d\n", Solve());
}
return 0;
}