HDU 3085 Nightmare 双向bfs

来源:互联网 发布:照片说话软件 编辑:程序博客网 时间:2024/05/01 15:12

传送门:HDU3085

题意:

  n*m地图上有

  ‘. ’:路

  X:墙

  Z:鬼,每秒蔓延2个单位长度,可以穿墙,共两个,每秒开始时鬼先动 

  M:每分钟可移动3个单位长度

  G:每分钟课移动1个单位长度

问两人是否可在不被鬼吃掉的前提下成功碰面

思路:双向bfs,即对两人同时bfs,若某人走的格子另一个人已经走过,则说明能碰面,停止搜索。鬼到人的距离可以用曼哈顿距离计算,若小于 等于两倍的时间就说明人被吃掉了。

代码:

#include<stdio.h>#include<iostream>#include<string.h>#include<math.h>#include<algorithm>#include<queue>#include<stack>#include<set>#include<vector>#include<map>#define ll long long#define pi acos(-1)#define inf 0x3f3f3f3fusing namespace std;typedef pair<int,int>P;int n,m;char mp[808][808];struct node{int r,c;}G,M,z[2];queue<node>q[2];int time=0;int go[4][2]={1,0,0,1,-1,0,0,-1};bool book[2][808][808];int bfs(int k){int cnt=q[k].size();while(cnt--)//把所有的情况都往前推进一步,切忌写成while(!q.empty()) {node t=q[k].front(),a;q[k].pop();if(abs(t.r-z[0].r)+abs(t.c-z[0].c)<=time*2)continue;if(abs(t.r-z[1].r)+abs(t.c-z[1].c)<=time*2)continue;for(int i=0;i<4;i++){a.r=t.r+go[i][0];a.c=t.c+go[i][1];if(a.c<0||a.r<0||a.r>=n||a.c>=m)continue;if(mp[a.r][a.c]=='X'||book[k][a.r][a.c])continue;if(abs(a.r-z[0].r)+abs(a.c-z[0].c)<=time*2)continue;if(abs(a.r-z[1].r)+abs(a.c-z[1].c)<=time*2)continue;if(book[k^1][a.r][a.c])return 1;book[k][a.r][a.c]=1;q[k].push(a);}}return 0;}int solve(){memset(book,0,sizeof(book));while(!q[0].empty())q[0].pop();while(!q[1].empty())q[1].pop();q[0].push(M);q[1].push(G);book[0][M.r][M.c]=1;book[1][G.r][G.c]=1;while((!q[0].empty())||(!q[1].empty()))//只要有一个人能走就还有会面的希望 {time++;if(bfs(0))return time;if(bfs(0))return time;if(bfs(0))return time;if(bfs(1))return time;} return -1;}int main(){intt;scanf("%d",&t);while(t--){scanf("%d%d",&n,&m);int cnt=0;time=0;for(int i=0;i<n;i++){scanf("%s",mp[i]);for(int j=0;j<m;j++){if(mp[i][j]=='G'){G.r=i;G.c=j;}if(mp[i][j]=='M'){M.r=i;M.c=j;}if(mp[i][j]=='Z'){z[cnt].r=i;z[cnt++].c=j;}}}printf("%d\n",solve()); }     return 0;}


0 0