题目链接:点击查看
题目大意:给出一个迷宫,一个男孩和一个女孩还有两只鬼,男孩每秒钟走3格,女孩每秒钟走1格,鬼每秒钟向四周分裂2格,问男孩和女孩能否在鬼占领迷宫之前汇合,能的话输出汇合时间,否则输出-1
题目分析:双向bfs模板题,不过在我看来双向bfs和单向bfs没什么区别,就是格式上有点不一样,对于这个题目每次男孩bfs一次,然后女孩bfs一次,注意实时判断当前格子是否已经被鬼占领,每次向外扩展的时候也不需要用vis数组标记重复了,只需要在原迷宫的基础上打上自己的特殊符号即可,只要另一方遍历到该符号即代表两人相遇,就可以及时返回了
这个题目有一个需要注意的地方,一开始没仔细看题目,想当然的以为M代表的是女生,G代表的是男生,结果正好相反了,当时调了有点时间,回去仔细读了一遍题才发现的。。
代码:
#include<iostream>
#include<cstdio>
#include<string>
#include<ctime>
#include<cstring>
#include<algorithm>
#include<stack>
#include<queue>
#include<map>
#include<sstream>
using namespace std;
typedef long long LL;
const int inf=0x3f3f3f3f;
const int N=810;
const int b[4][2]={0,1,0,-1,1,0,-1,0};
int n,m,k,step,ans;
char maze[N][N];
struct Node
{
int x,y;
Node(int X,int Y)
{
x=X;
y=Y;
}
Node(){}
}ghost[2];
queue<Node>gg,mm;
bool check(int x,int y)
{
if(x<0||y<0||x>=n||y>=m)
return false;
if(maze[x][y]=='X')
return false;
for(int i=0;i<2;i++)
if(step*2>=abs(x-ghost[i].x)+abs(y-ghost[i].y))
return false;
return true;
}
bool bfsgg()
{
for(int tt=1;tt<=3;tt++)
{
queue<Node>q(gg);
while(!q.empty())
{
Node cur=q.front();
q.pop();
gg.pop();
if(!check(cur.x,cur.y))
continue;
for(int i=0;i<4;i++)
{
int xx=cur.x+b[i][0];
int yy=cur.y+b[i][1];
if(!check(xx,yy))
continue;
if(maze[xx][yy]=='M')
continue;
if(maze[xx][yy]=='G')
return true;
maze[xx][yy]='M';
gg.push(Node(xx,yy));
}
}
}
return false;
}
bool bfsmm()
{
queue<Node>q(mm);
while(!q.empty())
{
Node cur=q.front();
q.pop();
mm.pop();
if(!check(cur.x,cur.y))
continue;
for(int i=0;i<4;i++)
{
int xx=cur.x+b[i][0];
int yy=cur.y+b[i][1];
if(!check(xx,yy))
continue;
if(maze[xx][yy]=='G')
continue;
if(maze[xx][yy]=='M')
return true;
maze[xx][yy]='G';
mm.push(Node(xx,yy));
}
}
return false;
}
bool solve()
{
while(!gg.empty())
gg.pop();
while(!mm.empty())
mm.pop();
step=k=0;
for(int i=0;i<n;i++)
for(int j=0;j<m;j++)
if(maze[i][j]=='G')
mm.push(Node(i,j));
else if(maze[i][j]=='M')
gg.push(Node(i,j));
else if(maze[i][j]=='Z')
{
ghost[k].x=i;
ghost[k].y=j;
k++;
}
while(!mm.empty()&&!gg.empty())
{
step++;
if(bfsgg()||bfsmm())
{
ans=step;
return true;
}
}
return false;
}
int main()
{
// freopen("input.txt","r",stdin);
int w;
cin>>w;
while(w--)
{
scanf("%d%d",&n,&m);
for(int i=0;i<n;i++)
scanf("%s",maze[i]);
if(solve())
printf("%d\n",ans);
else
printf("-1\n");
}
return 0;
}