HDU 3085 Nightmare Ⅱ(双向BFS)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3085

题目大意:给你一张n*m地图上,上面有有

  ‘. ’:路

  ‘X':墙

  ’Z':鬼,每秒移动2步,可以穿墙,开始有两个,每开始时鬼先动。

  ‘M’:男生,每秒可走3步。

  ‘G’:女生,每秒可走1步。

解题思路:第一次写双向BFS,写了我好久,开始还是想着先bfs计算step[x][y][t]把每个位置被鬼占据的时间处理一下然后再用双向BFS计算两人相遇时间。后来发现因为鬼可以穿墙,可以直接用曼哈顿距离判断是否会被鬼抓到。还有,开始我都不知道每秒走三步怎么搞。。。后来看了网上的博客,知道可以通用size限制一下出队数,三次bfs实现每秒走三步。太乱了,稍微总结一下:

     ①两人给vis[x][y]分别标记1,2当某次bfs遇到不同标记说明两人相遇。

     ②用曼哈顿距离判断时间t走到某个位置是否会被鬼抓到。

     ③因为鬼先行动,每次t+1时,在人行动前要判断在当前位置会不会被鬼抓到。

     ④用size=q[mark].size()控制每次出队数,实现一秒走三步。

     ⑤最坑爹的一点,用scanf("%c",&map[i][j])无限超时,感觉里面绝对有不正常的数据,后来用scanf("%s",map[i]+1)每次输入一行才过掉。

代码:

  1 #include<iostream>
  2 #include<queue>
  3 #include<cstdio>
  4 #include<cstring>
  5 #include<algorithm>
  6 using namespace std;
  7 const int N=805;
  8 
  9 int n,m,t;
 10 int d[4][2]={{-1,0},{1,0},{0,-1},{0,1}};
 11 char map[N][N];
 12 int vis[N][N];
 13 
 14 struct node{
 15     int x,y;
 16 }M,G,pre,now,a[3];
 17 queue<node>q[3];
 18 
 19 bool judge(int x,int y){
 20     if(x<1||y<1||x>n||y>m||map[x][y]=='X')
 21         return false;
 22     //利用曼哈顿距离判断是否会被鬼抓到 
 23     for(int i=1;i<=2;i++){
 24         if(abs(x-a[i].x)+abs(y-a[i].y)<=2*t)
 25             return false;
 26     }
 27     return true;
 28 }
 29 
 30 bool bfs(int mark){
 31     //小技巧,利用size就可以控制出队的都是上一步的,而不会将这一步的也出队,就能实现走3步了。 
 32     int size=q[mark].size(); 
 33     while(size--){
 34         pre=q[mark].front();
 35         q[mark].pop();
 36         //鬼在人之前行动,时间每增加1,先判断鬼能不能把人吃掉
 37         if(!judge(pre.x,pre.y)) 
 38             continue;
 39         for(int i=0;i<4;i++){
 40             int xx=pre.x+d[i][0];
 41             int yy=pre.y+d[i][1];
 42             if(!judge(xx,yy))
 43                 continue;
 44             //遇到不同标记说明两人相遇 
 45             if(vis[xx][yy]){
 46                 if(vis[xx][yy]!=mark)
 47                     return true;
 48                 else
 49                     continue;
 50             }
 51             vis[xx][yy]=mark;
 52             now.x=xx;
 53             now.y=yy;
 54             q[mark].push(now);
 55         }
 56     }
 57     return false;
 58 }
 59 
 60 int solve(){
 61     //清空队列 
 62     while(!q[1].empty()) q[1].pop();
 63     while(!q[2].empty()) q[2].pop();
 64     q[1].push(M);
 65     q[2].push(G);
 66     vis[M.x][M.y]=1,vis[G.x][G.y]=2;
 67     t=0;
 68     //双向bfs 
 69     while(!q[1].empty()||!q[2].empty()){
 70         t++;
 71         for(int i=1;i<=3;i++){
 72             if(bfs(1))
 73                 return t;
 74         }        
 75         if(bfs(2))
 76             return t;
 77     }
 78     return -1;
 79 }
 80 
 81 int main(){
 82     int T;
 83     scanf("%d",&T);
 84     while(T--){
 85         memset(vis,0,sizeof(vis));
 86         scanf("%d%d",&n,&m);
 87         //注意用scanf("%c",map[i][j])会超时 
 88         for(int i=1,cnt=0;i<=n;i++){
 89             scanf("%s",map[i]+1);
 90             for(int j=1;j<=m;j++){
 91                 if(map[i][j]=='M')
 92                     M.x=i,M.y=j;
 93                 if(map[i][j]=='G')
 94                     G.x=i,G.y=j;
 95                 if(map[i][j]=='Z')
 96                     a[++cnt].x=i,a[cnt].y=j;
 97             }
 98         }
 99         printf("%d\n",solve());
100     }
101     return 0;
102 }

 

posted @ 2017-09-22 19:32  Yeader  阅读(365)  评论(0编辑  收藏  举报