题面描述
思路
本文有
N
∗
M
N*M
N∗M的地图,字符
X
X
X表示墙,
.
\large .
.表示路,
1
1
1个
b
o
y
boy
boy,位置在
M
M
M,
1
1
1个
g
i
r
l
girl
girl,位置在
G
G
G,
2
2
2个
g
h
o
s
t
ghost
ghost,位置在
Z
Z
Z,
b
o
y
boy
boy每秒可以在道路上移动三个单位距离,
g
i
r
l
girl
girl在道路上移动一个单位距离,每个
g
h
o
s
t
ghost
ghost占据的区域每秒可以向四周扩张
2
2
2个单位距离,且无视墙的阻挡,也就是在第
k
k
k秒后所有与鬼的曼哈顿距离不超过
2
∗
k
2*k
2∗k的位置都会被鬼占领.
求在不进入鬼的占领区的前提下,男孩与女孩能否会合,若能会合求出最短会合时间。
1
≤
N
,
M
≤
800
1\le N,M \le 800
1≤N,M≤800
其实观察题面
b
o
y
boy
boy每秒可以在道路上移动三个单位距离,
g
i
r
l
girl
girl在道路上移动一个单位距离
我们就可以定义bfs的状态:
也就是男孩
b
f
s
3
bfs~3
bfs 3次,女孩
b
f
s
1
bfs~1
bfs 1次。再加判断判定此状态时候合法,要实时更新与鬼的曼哈顿距离,即可。
代码
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<cstdlib>
#include<queue>
using namespace std;
const int N=810;
const int dx[4]={0,0,-1,1};
const int dy[4]={-1,1,0,0};
struct node
{
int x,y;
node(){}
node(int x,int y):x(x),y(y){}
};
char s[N][N];bool v1[N][N],v2[N][N];
int n,m,px,py,qy,qx;
inline int myabs(int x){return x<0?-x:x;}
bool pd(int x,int y,int k)
{
if(x<=0||x>n||y<=0||y>m)return false;
if(s[x][y]=='X')return false;
if(myabs(x-px)+myabs(y-py)<=2*k)return false;
if(myabs(x-qx)+myabs(y-qy)<=2*k)return false;
return true;
}
void bfs()
{
for(int i=1;i<=n;i++)
scanf("%s",s[i]+1);
int bx,by,gx,gy;px=py=qx=qy=0;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
{
if(s[i][j]=='M')bx=i,by=j;
if(s[i][j]=='G')gx=i,gy=j;
if(s[i][j]=='Z')
{
if(!px&&!py)px=i,py=j;
else qx=i,qy=j;
}
}
memset(v1,false,sizeof(v1));memset(v2,false,sizeof(v2));
queue<node>q1,q2;int ans=0;
q1.push(node(bx,by)),q2.push(node(gx,gy));
while(!q1.empty()||!q2.empty())
{
ans++;
for(int t=1;t<=3;t++)
{
int len=q1.size();
for(int k=1;k<=len;k++)
{
node t=q1.front();q1.pop();
if(!pd(t.x,t.y,ans))continue;
for(int i=0;i<4;i++)
{
node nxt=t;
nxt.x+=dx[i];nxt.y+=dy[i];
if(!pd(nxt.x,nxt.y,ans)||v1[nxt.x][nxt.y])continue;
v1[nxt.x][nxt.y]=true;
q1.push(nxt);
}
}
}
int len=q2.size();
for(int k=1;k<=len;k++)
{
node t=q2.front();q2.pop();
if(!pd(t.x,t.y,ans))continue;
for(int i=0;i<4;i++)
{
node nxt=t;
nxt.x+=dx[i];nxt.y+=dy[i];
if(!pd(nxt.x,nxt.y,ans)||v2[nxt.x][nxt.y])continue;
if(v1[nxt.x][nxt.y]){printf("%d\n",ans);return ;}
v2[nxt.x][nxt.y]=true;
q2.push(nxt);
}
}
}
puts("-1");
}
int main()
{
int t;scanf("%d",&t);
while(t--)
{
scanf("%d%d",&n,&m);
bfs();
}
return 0;
}