在一个迷宫中,有一个男孩,一个女孩,和两个鬼,男孩一次可以走三步,女的只能走一步,都只能走上下左右。
然后鬼每次就会向四周扩张两个距离,就是 k 秒后与鬼哈曼顿距离不超过 2×k 的地方都会被占领,人不能走到鬼占领的地方。
(每秒鬼先扩张,然后人再行动)
问两人能会和的最短时间,若不能会和,则输出 -1。
因为它是要相遇,而且一个人走三步一个人走一步。
那如果没有鬼的话你就在一步内让男的行动三次,让女的行动一次。
但是有鬼。
那你就记录一下在这一步的地方待着会不会被鬼抓。
而且有个特殊的就是如果说两个人走完相遇,而且他们走的路径在他们走之前都没有被鬼占领,也是可以的。(就算到下一轮鬼先行动会占领他们相遇的点)
#include
#include
#include
#include
using namespace std;
struct xx {
int x, y, dis;
}now;
bool a[1001][1001], in_b[1001][1001], in_g[1001][1001];
int T, re, f, n, m, mx, my, gx, gy, zx[3], zy[3], tmp;
int dx[4] = {
1, -1, 0, 0}, dy[4] = {
0, 0, 1, -1};
queue <xx> q_b, q_g;
char c;
int read() {
re = 0;
f = 1;
c = getchar();
while (c < '0' || c > '9') {
if (c == '-') f = -f;
c = getchar();
}
while (c >= '0' && c <= '9') {
re = re * 10 + c - '0';
c = getchar();
}
return re * f;
}
bool ingoest(int x, int y, int dis) {
//判断是否会被鬼抓
for (int i = 1; i <= 2; i++) {
if (abs(x - zx[i]) + abs(y - zy[i]) <= 2 * dis + 2) return 1;
}
return 0;
}
bool ch(int x, int y) {
if (x < 1 || x > n) return 0;
if (y < 1 || y > m) return 0;
return 1;
}
bool bfs() {
while (!q_g.empty()) q_g.pop();
while (!q_b.empty()) q_b.pop();
memset(in_g, 0, sizeof(in_g));
memset(in_b, 0, sizeof(in_b));
q_b.push((xx){
mx, my, 0});
in_b[mx][my] = 1;
q_g.push((xx){
gx, gy, 0});
in_g[gx][gy] = 1;
while (!q_b.empty() || !q_g.empty()) {
if (!q_b.empty()) {
//男孩行动
for (int step = 1; step <= 3; step++) {
//因为走三步,就可以看成走三步不需要步数,再最后加上一步
tmp = q_b.size();
for (int num = 1; num <= tmp; num++) {
now = q_b.front();
q_b.pop();
if (ingoest(now.x, now.y, now.dis)) continue;
for (int i = 0; i < 4; i++)
if (ch(now.x + dx[i], now.y + dy[i]))
if (!in_b[now.x + dx[i]][now.y + dy[i]] && a[now.x + dx[i]][now.y + dy[i]]) {
if (!ingoest(now.x + dx[i], now.y + dy[i], now.dis) && in_g[now.x + dx[i]][now.y + dy[i]]) {
printf("%d\n", now.dis + 1);
return 1;
}
in_b[now.x + dx[i]][now.y + dy[i]] = 1;
q_b.push((xx){
now.x + dx[i], now.y + dy[i], now.dis});
}
}
}
tmp = q_b.size();
for (int num = 1; num <= tmp; num++) {
//最后加上一步
now = q_b.front();
q_b.pop();
q_b.push((xx){
now.x, now.y, now.dis + 1});
}
}
if (!q_g.empty()) {
//女孩走
tmp = q_g.size();
for (int num = 1; num <= tmp; num++) {
now = q_g.front();
q_g.pop();
if (!ingoest(now.x, now.y, now.dis)) {
for (int i = 0; i < 4; i++)
if (ch(now.x + dx[i], now.y + dy[i]))
if (!in_g[now.x + dx[i]][now.y + dy[i]] && a[now.x + dx[i]][now.y + dy[i]]) {
if (!ingoest(now.x + dx[i], now.y + dy[i], now.dis) && in_b[now.x + dx[i]][now.y + dy[i]]) {
printf("%d\n", now.dis + 1);
return 1;
}
in_g[now.x + dx[i]][now.y + dy[i]] = 1;
q_g.push((xx){
now.x + dx[i], now.y + dy[i], now.dis + 1});
}
}
}
}
}
return 0;
}
int main() {
T = read();
for (int times = 1; times <= T; times++) {
n = read();
m = read();
zx[0] = 0;
for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; j++) {
c = getchar();
while (c != 'X' && c != 'Z' && c != '.' && c != 'M' && c != 'G') c = getchar();
if (c == '.' || c == 'M' || c == 'G') {
a[i][j] = 1;
if (c == 'M') {
mx = i;
my = j;
}
if (c == 'G') {
gx = i;
gy = j;
}
}
if (c == 'Z') {
zx[++zx[0]] = i;
zy[zx[0]] = j;
a[i][j] = 0;
}
if (c == 'X') a[i][j] = 0;
}
if (!bfs()) printf("-1\n");
}
return 0;
}