# kuangbin专题 专题二 搜索进阶 Nightmare Ⅱ HDU - 3085

### 题目链接：https://vjudge.net/problem/HDU-3085

‘Z’表示鬼。

  1 #include <iostream>
2 #include <cstring>
3 #include<vector>
4 #include <cstdio>
5 #include<string>
6 #include <cmath>
7 #include <map>
8 #include <queue>
9 #include <algorithm>
10 using namespace std;
11
12 #define inf (1LL << 31) - 1
13 #define rep(i,j,k) for(int i = (j); i <= (k); i++)
14 #define rep__(i,j,k) for(int i = (j); i < (k); i++)
15 #define per(i,j,k) for(int i = (j); i >= (k); i--)
16 #define per__(i,j,k) for(int i = (j); i > (k); i--)
17
18 const int N  = 810;
19 int mv_x[] = {0, 0, 1, -1};
20 int mv_y[] = {1, -1, 0, 0};
21 char mp[N][N]; //原始地图
22 int mx,my,hx,hy; //男女的坐标
23 int g_x[2],g_y[2],g_l; //两个鬼的坐标
24 int n,m,STEP;
25
26 struct node{
27     int x,y;
28 };
29
30 queue <node > que[2];
31 queue <node > qt;
32
33 inline void init(){
34     g_l = 0;
35     STEP = 0;
36 }
37
38 void input(){
39
40     init();
41
42     rep(i,1,n){
43         rep(j,1,m){
44             cin >> mp[i][j];
45             if(mp[i][j] == 'M') mx = i, my = j;
46             else if(mp[i][j] == 'G') hx = i, hy = j;
47             else if(mp[i][j] == 'Z') g_x[g_l] = i, g_y[g_l++] = j;
48         }
49     }
50 }
51
52 //是否越界
53 inline bool check(int x, int y){
54     return x >= 1 && x <= n && y >= 1 && y <= m;
55 }
56
57 //曼哈顿距离判断能不能相遇
58 inline bool M_dis(int dx,int dy){
59
60     rep__(i,0,2){
61         if(abs(dx - g_x[i]) + abs(dy - g_y[i]) <= 2 * STEP) return false;
62     }
63     return true;
64 }
65
66 void show(){
67
68     rep(i,1,n){
69         rep(j,1,m) cout << mp[i][j];
70         cout << endl;
71     }
72 }
73
74 bool bfs(int pos, int steps, char me, char another){
75
76
77
78     rep(i,1,steps){ //一个行程走几轮
79         qt = que[pos];  //把这轮的所有开始点复制给qt
80
81         while(!qt.empty()){
82
83             node tmp = qt.front();
84             qt.pop();
85             que[pos].pop();
86
87             if(!M_dis(tmp.x,tmp.y)) continue; //刚开始进入bfs判断一次曼哈顿距离，先判断下人没走之前鬼是不是能抓到人
88
89             rep__(p,0,4){
90
91                 int dx = tmp.x + mv_x[p];
92                 int dy = tmp.y + mv_y[p];
93
94                 //没越界   不是墙  不是鬼  自己没走过  满足曼哈顿距离
95                 if(check(dx, dy) && mp[dx][dy] != 'X' && mp[dx][dy] != 'Z' &&  mp[dx][dy] != me
96 　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　&& M_dis(dx,dy)){
97
98                     if(mp[dx][dy] == another){ //遇到了另一个人
99
100                         // cout << "find the position  " << dx << "  " << dy << endl;
101                         // cout << me  <<" find " << mp[dx][dy] << endl;
102                         return true;
103                     }
104
105                     mp[dx][dy] = me; //标记自己走过了这里
106                     que[pos].push(node{ dx, dy });//存在que[]中，表示下一轮的开始点
107                 }
108             }
109         }
110     }
111
112     return false;
113 }
114
115 bool solve(){
116
117     while (!que[0].empty()) que[0].pop();
118     while (!que[1].empty()) que[1].pop();
119     while (!qt.empty()) qt.pop();
120 　　//que[0]表示M，que[1]表示G
121     que[0].push(node{ mx, my });
122     que[1].push(node{ hx, hy });
123
124     while (!que[0].empty() && !que[1].empty()){ // && 和 ||  其实都可以  &&说明一个人不能走了 　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　  //那么另一个人也一定没地方走了
125
126         STEP++;//步数加一，其实更好理解为行程加一
127         if(bfs(0, 3,'M','G') || bfs(1, 1,'G','M')) return true;
128
129     }
130
131     return false;
132 }
133
134 int main(){
135
136     ios::sync_with_stdio(false);
137     cin.tie(0);
138
139     int T;
140     cin >> T;
141     while (T--){
142         cin >> n >> m;
143         input();
144
145         if(solve()) cout << STEP << endl;
146         else cout << "-1" << endl;
147     //    show();
148     //    cout << endl;
149     }
150
151 //    getchar();
152
153     return 0;
154 }

posted @ 2019-07-14 14:08  SummerMingQAQ  阅读(126)  评论(0编辑  收藏