【ybtoj】【BFS】【例题6】逃离噩梦

【例题6】逃离噩梦


Link

传送门
题目


解题思路

ybtoj交完心平气和,两天后杭州oj交完心态爆炸
这件事教会了zzl打题要用快读

鬼的覆盖范围不需要特别处理,只需要O(1)判断一下走没走到鬼的覆盖范围

接下来就是boy & girl了,
每秒boy走三步,girl走一步就很迷: )
他俩必须同时BFS,但是是两个不同的队列
那么boy直接就加一层循环寻三步就欧克了
boy走到的点标记为1,girl走过的点标记为2,那么1和2第一次出现同一格时就是会和了

STL——pair函数
新学的一个函数
(个人理解)
就是把两个元素绑在一起(类似一个struct node{int first, second;};)

  • 定义
#include <iostream>
#include <cstdio>

*#include <utility>*

using namespace std;

pair<int, int> a;
pair<string, int> b;

一个pair<>里面可以放两个元素
比如:a里面可以放两个int,b里面first放string类型,second放int类型

  • 小用法
pair<int, int> now;
int a, b;

now = make_pair(a, b);

make_pair可以将两个。。变量(?)合(?)成一个pair


Code

#include <iostream>
#include <utility>
#include <cstring>
#include <cstdio>
#include <queue>
#include <cmath>

using namespace std;

const int way[4][2] = {
    
    {
    
    -1, 0}, {
    
    1, 0}, {
    
    0, -1}, {
    
    0, 1}};
queue< pair<int, int> > q_boy, q_girl;
pair<int, int> ghost[2], now;
int T, n, m, xx, yy, v[810][810];
char a[810][810];

inline int read() {
    
    //什么神仙题目,数据有毒就直接把快读贴出来
	int x = 0, f = 1; char s = getchar();
	while (s < '0' || s > '9') {
    
     if (s == '-') f = -f; s = getchar(); }
	while (s >= '0' && s <= '9') {
    
     x = x * 10 + s - '0'; s = getchar(); }
	return x * f;
}

char readc() {
    
    //什么垃圾题目,不是说不想用快读去杭州oj交吗,为什么不加快读就超时
	char c = getchar();
	while((c > 'Z' || c < 'A') && c != '.') c = getchar();
	return c;
}

bool check(int x, int y, int min) {
    
    
	if (x < 1 || x > n || y < 1 || y > m || a[x][y] == 'X')
		return 0;
	for (int i = 0; i < 2; i++)
		if ((abs(x - ghost[i].first) + abs(y - ghost[i].second)) <= 2 * min)//判断有没有走到鬼覆盖范围
			return 0;
	return 1;
}

void BFS() {
    
    
	int min = 0;//记录时间
	while(!q_boy.empty() || !q_girl.empty()) {
    
    
		min++;
		for (int step = 1; step <= 3; step++)//boy走3步
			for (int oie = q_boy.size(); oie; oie--) {
    
    //因为中途会push进一些点,所以必须倒序
				now = q_boy.front();
				q_boy.pop();
				if (!check(now.first, now.second, min))
					continue;
				for (int i = 0; i < 4; i++) {
    
    
					xx = now.first + way[i][0], yy = now.second + way[i][1];
					if (!check(xx, yy, min))
						continue;
					if (v[xx][yy] != 1) {
    
    //boy没走过
						if (v[xx][yy] == 2) {
    
    //girl走过这个点
							printf("%d\n", min);
							return;
						}
						q_boy.push(make_pair(xx, yy));
						v[xx][yy] = 1;
					}
				}
			}
		for (int oie = q_girl.size(); oie; oie--) {
    
    //girl同上
			now = q_girl.front();
			q_girl.pop();
			if (!check(now.first, now.second, min))
				continue;
			for (int i = 0; i < 4; i++) {
    
    
				xx = now.first + way[i][0], yy = now.second + way[i][1];
				if (!check(xx, yy, min))
					continue;
				if (v[xx][yy] != 2) {
    
    
					if (v[xx][yy] == 1) {
    
    
						printf("%d\n", min);
						return;
					}
					q_girl.push(make_pair(xx, yy));
					v[xx][yy] = 2;
				}
			}
		}
	}
	printf("-1\n");
}

int main() {
    
    
	T = read();
	while (T--) {
    
    
		memset(v, 0, sizeof(v));
		while(!q_boy.empty())
			q_boy.pop();
		while(!q_girl.empty())
			q_girl.pop();
		n = read(), m = read();
		int cnt = 0;
		for (int i = 1; i <= n; i++) {
    
    
			for (int j = 1; j <= m; j++) {
    
    
				a[i][j] = readc();//(怒 ̄へ ̄)
				if (a[i][j] == 'Z')
					ghost[cnt++] = make_pair(i, j);//记录鬼的位置
				if (a[i][j] == 'M') {
    
    
					q_boy.push(make_pair(i, j));//将boy放进boy的队列里
					v[i][j] = 1;//标记为boy走过的点
				}
				if (a[i][j] == 'G') {
    
    
					q_girl.push(make_pair(i, j));//将girl放进girl的队列里 
					v[i][j] = 2;//标记为girl走过的点
				}
			}
		}
		BFS();
	}
}

猜你喜欢

转载自blog.csdn.net/qq_39940018/article/details/112999465