版权声明:本文为博主原创作品, 转载请注明出处! https://blog.csdn.net/solider98/article/details/84317162
思路分析:
考虑对男孩和和女孩各自使用BFS, 男孩的解空间树每次搜索三层对应男孩每秒钟可走三步, 女孩的解空间树每次搜一层, 对应女孩每秒钟可走一步, 同时注意第k秒时, 所有与初始两个鬼的曼哈顿距离不超过2k均被鬼覆盖, 下面给出基于此思想的AC代码:
//HDOJ3085_Nightmare Ⅱ
#include <iostream>
#include <cstdio>
#include <queue>
#include <cstring>
#include <cmath>
#include <algorithm>
#define mp make_pair
#define fi first
#define se second
using namespace std;
typedef pair<int, int> pii;
const int MAX = 805, INF = 0x3f3f3f3f, dx[4] = {-1, 1, 0, 0}, dy[4] = {0, 0, -1, 1};
char G[MAX][MAX]; int n, m;
int bx, by, gx, gy, zx1, zy1, zx2, zy2;//男孩, 女孩, 鬼1, 鬼2的起始位置
bool b[MAX][MAX], g[MAX][MAX];//[i][j]为true表示i行j列已被处理, 为false未被处理
int main(){
int T; scanf("%d", &T);
while(T--){
scanf("%d %d", &n, &m); for(int i = 1; i <= n; ++i) scanf("%s", G[i] + 1);
//初始化男孩, 女孩, 鬼1, 鬼2起始位置
zx1 = 0;
for(int i = 1; i <= n; ++i)
for(int j = 1; j <= m; ++j){
if(G[i][j] == 'M') bx = i, by = j, G[i][j] = '.';
if(G[i][j] == 'G') gx = i, gy = j, G[i][j] = '.';
if(G[i][j] == 'Z' && !zx1) zx1 = i, zy1 = j, G[i][j] = '.';
if(G[i][j] == 'Z' && zx1) zx2 = i, zy2 = j, G[i][j] = '.';
}
memset(b, false, sizeof(b)), memset(g, false, sizeof(g));
queue<pii> bq, gq;//男孩, 女孩的队列
bq.push(mp(bx, by)), bq.push(mp(INF, INF)), b[bx][by] = true;
gq.push(mp(gx, gy)), gq.push(mp(INF, INF)), g[gx][gy] = true;
int ti = 0, res = INF;//ti当前时间
while(++ti, bq.size() >= 2 || gq.size() >= 2){
//搜索bq中的三层
for(int i = 1; i <= 3 && !bq.empty(); ++i){
while(!bq.empty()){
int x = bq.front().fi, y = bq.front().se; bq.pop();
if(x == INF) break;
if(abs(x - zx1) + abs(y - zy1) <= 2 * ti
|| abs(x - zx2) + abs(y - zy2) <= 2 * ti) continue;
for(int j = 0; j <= 3; ++j){
int u = x + dx[j], v = y + dy[j];
if(u >= 1 && u <= n && v >= 1 && v <= m && G[u][v] == '.' && !b[u][v]
&& abs(u - zx1) + abs(v - zy1) > 2 * ti
&& abs(u - zx2) + abs(v - zy2) > 2 * ti){
if(g[u][v]){
res = ti; goto P1;
}
b[u][v] = true, bq.push(mp(u, v));
}
}
}
bq.push(mp(INF, INF));
}
//搜索gq中的一层
while(!gq.empty()){
int x = gq.front().fi, y = gq.front().se; gq.pop();
if(x == INF) break;
if(abs(x - zx1) + abs(y - zy1) <= 2 * ti
|| abs(x - zx2) + abs(y - zy2) <= 2 * ti) continue;
for(int j = 0; j <= 3; ++j){
int u = x + dx[j], v = y + dy[j];
if(u >= 1 && u <= n && v >= 1 && v <= m && G[u][v] == '.' && !g[u][v]
&& abs(u - zx1) + abs(v - zy1) > 2 * ti
&& abs(u - zx2) + abs(v - zy2) > 2 * ti){
if(b[u][v]){
res = ti; goto P1;
}
g[u][v] = true, gq.push(mp(u, v));
}
}
}
gq.push(mp(INF, INF));
}
P1: if(res == INF) cout << -1 << endl; else cout << res << endl;
}
return 0;
}