HDOJ3085 Nightmare Ⅱ 双向BFS

题目链接

http://acm.hdu.edu.cn/showproblem.php?pid=3085

分析

从男孩和女孩的起点开始分别BFS,男孩每次扩展三层,女孩每次扩展一层,且保证每一时刻 t t t 到鬼的曼哈顿距离不超过 2 ∗ t 2 * t 2t

注意是鬼先走,当某次扩展到的节点对方已经走过,说明两人相遇。

AC代码

#include 
#include 
#include 
#include 

using namespace std;

inline int read() {
	int num = 0;
	char c = getchar();
	while (c < '0' || c > '9') c = getchar();
	while (c >= '0' && c <= '9')
		num = num * 10 + c - '0', c = getchar();
	return num;
}

const int maxn = 805;
const int nxt[4][2] = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}};

struct Node {
	int x, y;
	
	Node(int x = 0, int y = 0) : x(x), y(y) {}
} b, g, z1, z2;

int n, m, v1[maxn][maxn], v2[maxn][maxn], ans;
char map[maxn][maxn];
queue<Node> q1, q2;

inline int judge(Node p) {
	if (p.x < 1 || p.x > n || p.y < 1 || p.y > m) return 0;
	if (map[p.x][p.y] == 'X') return 0;
	if (abs(p.x - z1.x) + abs(p.y - z1.y) <= 2 * ans) return 0;
	if (abs(p.x - z2.x) + abs(p.y - z2.y) <= 2 * ans) return 0;
	return 1;
}

inline void bmove(int cnt) {
	for (int i = 1; i <= cnt; ++i) {
		Node u = q1.front(), v;
		q1.pop();
		if (!judge(u)) continue;
		for (int j = 0; j < 4; ++j) {
			v.x = u.x + nxt[j][0], v.y = u.y + nxt[j][1];
			if (!judge(v) || v1[v.x][v.y]) continue;
			v1[v.x][v.y] = 1;
			q1.push(v);
		}
	}
}

inline int bfs() {
	memset(v1, 0, sizeof(v1));
	memset(v2, 0, sizeof(v2));
	ans = 0;
	while (!q1.empty()) q1.pop();
	while (!q2.empty()) q2.pop();
	v1[b.x][b.y] = v2[g.x][g.y] = 1;
	q1.push(b), q2.push(g);
	while (!q1.empty() || !q2.empty()) {
		++ans;
		for (int i = 1; i <= 3; ++i) bmove(q1.size());
		int cnt = q2.size();
		for (int i = 1; i <= cnt; ++i) {
			Node u = q2.front(), v;
			q2.pop();
			if (!judge(u)) continue;
			for (int j = 0; j < 4; ++j) {
				v.x = u.x + nxt[j][0], v.y = u.y + nxt[j][1];
				if (!judge(v) || v2[v.x][v.y]) continue;
				if (v1[v.x][v.y]) return ans;
				v2[v.x][v.y] = 1;
				q2.push(v);
			}
		}
	}
	return -1;
}

int main() {
	int t = read();
	while (t--) {
		n = read(), m = read();
		z1.x = 0;
		for (int i = 1; i <= n; ++i) {
			scanf("%s", map[i] + 1);
			for (int j = 1; j <= m; ++j) {
				if (map[i][j] == 'M') b.x = i, b.y = j;
				else if (map[i][j] == 'G') g.x = i, g.y = j;
				else if (map[i][j] == 'Z') {
					if (!z1.x) z1.x = i, z1.y = j;
					else z2.x = i, z2.y = j;
				}
			}
		}
		printf("%d\n", bfs());
	}
	return 0;
}

你可能感兴趣的:(《算法竞赛进阶指南》)