【ybt高效进阶1-5-6】【HDU 3085】逃离噩梦 / Nightmare Ⅱ

逃离噩梦 / Nightmare Ⅱ

题目链接:ybt高效进阶1-5-6 \ HDU 3085

题目大意

在一个迷宫中,有一个男孩,一个女孩,和两个鬼,男孩一次可以走三步,女的只能走一步,都只能走上下左右。

然后鬼每次就会向四周扩张两个距离,就是 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;
}

你可能感兴趣的:(#,dfs或bfs,bfs)