版权声明:转载请注明原出处啦QAQ(虽然应该也没人转载): https://blog.csdn.net/hzk_cpp/article/details/89787030
题目:hdu3085.
题目大意:给定一个
的网格,网格上有一对男女和两个鬼,男孩每秒钟最多走三格,女孩每秒钟最多走一格,鬼在第
秒会占领所有曼哈顿距离它
以内的格子,求男孩和女孩最快多久可以相遇且不经过鬼占领的区域.
.
双向bfs的入门题,感觉没什么好说的,但作为板子还是说一点吧…
大家都知道双向bfs的原理,这里就说一点实现细节.可以用两个队列直接男孩和女孩的状态,把每一次拓展都写成一个函数,男孩拓展的时候调用三次这个函数,女孩拓展的时候调用一次,鬼可以直接用时间判,其它应该就没什么了…
代码如下:
#include<bits/stdc++.h>
using namespace std;
#define Abigail inline void
typedef long long LL;
const int N=800;
const int dx[4]={0,0,1,-1};
const int dy[4]={1,-1,0,0};
char Rc(){
char c=getchar();
while (c^'.'&&(c<'A'||c>'Z')) c=getchar();
return c;
}
int n,m;
char b[N+9][N+9];
struct node{
int x,y;
node(int X=0,int Y=0){x=X;y=Y;}
}gh[2],M,G;
bool Catch(node x,int t){
if (abs(x.x-gh[0].x)+abs(x.y-gh[0].y)<=t<<1) return 1;
if (abs(x.x-gh[1].x)+abs(x.y-gh[1].y)<=t<<1) return 1;
return 0;
}
queue<node>q[2];
bool vis[2][N+9][N+9];
bool Bfs(int id,int tm){
int siz=q[id].size();
node t,nt;
while (siz--){
t=q[id].front();q[id].pop();
if (Catch(t,tm)) continue;
for (int i=0;i<4;++i){
nt=node(t.x+dx[i],t.y+dy[i]);
if (nt.x<1||nt.x>n||nt.y<1||nt.y>m) continue;
if (b[nt.x][nt.y]=='X'||b[nt.x][nt.y]=='Z') continue;
if (vis[id][nt.x][nt.y]) continue;
if (Catch(nt,tm)) continue;
vis[id][nt.x][nt.y]=1;
if (vis[id^1][nt.x][nt.y]) return 1;
q[id].push(nt);
}
}
return 0;
}
int Solve(){
for (int i=1;i<=n;++i)
for (int j=1;j<=m;++j)
vis[0][i][j]=vis[1][i][j]=0;
for (int i=0;i<2;++i)
while (!q[i].empty()) q[i].pop();
vis[0][M.x][M.y]=1;
vis[1][G.x][G.y]=1;
q[0].push(M);
q[1].push(G);
int tm=0;
while (!q[0].empty()||!q[1].empty()){
++tm;
for (int i=0;i<3;++i)
if (Bfs(0,tm)) return tm;
if (Bfs(1,tm)) return tm;
}
return -1;
}
Abigail into(){
scanf("%d%d",&n,&m);
int cgh=0;
for (int i=1;i<=n;++i)
for (int j=1;j<=m;++j){
b[i][j]=Rc();
if (b[i][j]=='Z') gh[cgh].x=i,gh[cgh++].y=j;
if (b[i][j]=='M') M.x=i,M.y=j;
if (b[i][j]=='G') G.x=i,G.y=j;
}
}
Abigail outo(){
printf("%d\n",Solve());
}
int main(){
int T;
scanf("%d",&T);
while (T--){
into();
outo();
}
return 0;
}