这道题题意:erriye 梦见女友被困在迷宫里了,现在 erriye 需要去解救他的的女友,给出他女友(G)和他的位置(M),迷宫里有两个ghost(Z),每秒钟会分生出多个ghost占据在他2步之内的所有格子(新出生的ghost每秒钟也会分生出多个ghost占据在他2步之内的所有格子),little erriye 每秒可以移动3步,grilfriend每秒可以移动一步,ghost、erriye、grilfriend都只能上下左右移动(且人不能穿透墙壁(X),鬼魂可以),人一旦与鬼魂占据同一格子,则被杀死。问:little erriye 最少需要多久才能解救其女友?(如果解救失败,输出-1,每一秒ghost先移动)
分析:我刚开始男,女,鬼BFS三遍,然后最后处理答案,严重超时,然后上网看题解,发现是双向BFS
就一秒一秒走就行,男的一秒走3,女的一秒走1,然后走过的分别赋值男女标记,当走到对方的标记时就是答案了(因为可以一个人不走,另一个人走)。然后因为两个鬼不受墙的限制,所以两个鬼的位置用曼哈顿距离搞一下就行。代码如下:
#include<cstdio>
#include<cstring>
#include<queue>
#include<cstdlib>
#include<cmath>
using namespace std;
struct node{
int x,y;
};
node z[2];
int T,N,M;
int step;
int vis[805][805];
char map[805][805];
int d[4][2]={0,1,1,0,-1,0,0,-1}; //四个方向
queue<node>q[3];
bool Judge(int x,int y){
if(x<1||y<1||x>N||y>M)return false; //越界
if(map[x][y]=='X')return false; //墙
int a=abs(z[0].x-x)+abs(z[0].y-y); //曼哈顿距离
int b=abs(z[1].x-x)+abs(z[1].y-y);
if(a<=step*2||b<=step*2)return false;
return true;
}
bool Bfs(int pos,int num){
int i,j;
q[2]=q[pos];
for(i=0;i<num;i++){
node s,e;
while(!q[2].empty()){
s=q[2].front();
q[2].pop();
q[pos].pop();
if(!Judge(s.x,s.y))continue;
for(j=0;j<4;j++){
int xx=d[j][0]+s.x;
int yy=d[j][1]+s.y;
if(!Judge(xx,yy))continue;
if(vis[xx][yy]==pos)continue;
if(vis[xx][yy]==(pos^1))return true; //走到对方的标记处
vis[xx][yy]=pos;
e.x=xx;
e.y=yy;
q[pos].push(e); //注意此处不能有q[2].push(e); 因为是每一个人每一秒钟广搜一层
}
}
q[2]=q[pos];
}
return false;
}
int Solve(){
while(!q[0].empty()||!q[1].empty()){
step++; //每一秒钟两个人分别Bfs一次
if(Bfs(0,3)||Bfs(1,1))return step;
}
return -1; //不能相遇
}
int main()
{
int i,j;
scanf("%d",&T);
while(T--){
scanf("%d %d",&N,&M);
for(i=1;i<=N;i++) //注意是从下标1开始储存 不是下标0
{
scanf("%s",map[i]+1);
}
for(int i=0; i<3; i++) //注意清空队列
{
while(!q[i].empty())
{
q[i].pop();
}
}
step=0;
int cnt=0;
for(i=1;i<=N;i++){
for(j=1;j<=M;j++){
vis[i][j]=-1;
if(map[i][j]=='M'){ //M走过的地方标记为0
node s;
s.x=i,s.y=j;
q[0].push(s);
vis[i][j]=0;
}
else if(map[i][j]=='G'){ //G走过的地方标记为1
node s;
s.x=i,s.y=j;
q[1].push(s);
vis[i][j]=1;
}
else if(map[i][j]=='Z'){ //记录两处Z的位置
z[cnt].x=i;
z[cnt].y=j;
cnt++;
}
}
}
printf("%d\n",Solve());
}
return 0;
}