Problem H. 小凡与英雄救美

问题 H: Problem H. 小凡与英雄救美

时间限制: 1 Sec 内存限制: 256 MB

题目描述
英雄救美的故事永不过时。在本题中,小凡将扮演英雄勇闯魔王的宫殿,来到公主身边。
小凡手上有着宫殿的完整地图,该地图可以看作一个 n × n 的网格图,每个网格即为一个房间,地 图上有 5 类房间:
”S”:代表初始时小凡所在的房间。
”E”:代表公主所在的房间,由于公主被魔王所囚禁,所以无法移动。
”X”:该房间内驻守着第一类怪物,宫殿侍从,该怪物同样不会移动。
”P”:该房间内驻守着第二类怪物,魔王士兵,该怪物同样不会移动。
”O”:该房间空空如也。
两个房间相邻,当且仅当所代表的网格之间存在公共边。(即每个房间最多与上下左右四个房间所相 邻,如果当前房间坐标为 (x y),则与其相邻房间的坐标分别是 (x y + 1) (x y − 1) (x + 1 y) (x − 1 y)
在每一步中,小凡可以移动到相邻的网格中。
由于小凡的精力有限,他不想和怪物做过多的缠斗。
对于小凡来说,如果存在一种从初始房间到公主所在房间的移动方式,过程中不会经过任何怪物驻 守的房间,输出”MAJOR VICTORY”;
否则,如果存在一种从初始房间到公主所在房间的移动方式,只会与其中的一类怪物相遇,输 出”NARROW VICTORY”;
否则,此时任何一种从初始房间到公主所在房间的移动方式,均会经过两类怪物所在的房间,此时输 出”LOSE ”。
输入
第一行包含一个整数 n(1 ≤ n ≤ 10),代表宫殿的大小。 第二行到第 n + 1 行每行包括一个长度为 n 的字符串,每个字符代表宫殿中每个房间的类型,字符 只存在”S”,”E”,”X”,”P”,”O” 五种,小凡的初始房间”S” 和公主所在的房间”E” 有且仅有一个。
输出
如果存在一种从初始房间到公主所在房间的移动方式,过程中不会经过任何怪物驻守的房间,输 出”MAJOR VICTORY ”;
否则,如果存在一种从初始房间到公主所在房间的移动方式,只会与其中的一类怪物相遇,输 出”NARROW VICTORY”;
否则,此时任何一种从初始房间到公主所在房间的移动方式,均会经过两类怪物所在的房间,此时输 出”LOSE ”。
样例输入
3
SOX
PPX
XXE
样例输出
NARROW VICTORY
提示
在该样例中,英雄只与一类怪物相遇的行走方式为:S(1 1) −> O(1 2) −> X(1 3) −> X(2 3) −>
E(3 3)

啊这,比赛的时候一看就直接dfs恩搜,真是一头闷到dfs里出不来了
校赛的题感觉这一道比较巧妙,其他的就不写了。
思路:把怪物所在的房间可以看做障碍:
当 ‘P’、‘X’都看做障碍的时候如果还能搜到终点说明有一条路可以完全不经过怪物的房间。如果上一个情况不存在,那么当把‘P’、‘X’中的其中一个怪物的房间看做障碍(P是障碍X不是、X是障碍P不是),如果两种情况下存在一个可以搜到终点那么就是题中的第二种情况,不然就是第三种情况。
想到将怪物看做障碍的话就很简单,不然就wa

#include<iostream>
#include<cstring>
#include<queue>
using namespace std;
struct point {
	int x, y;
};
char maps[15][15];
bool vis[15][15];
int dir[4][2] = { -1,0,1,0,0,-1,0,1 };
int n;
int sx, sy, ex, ey;
bool bfs(char block1,char block2) {//block:障碍种类
	memset(vis, 0, sizeof(vis));
	queue<point> q;
	point p;
	p.x = sx, p.y = sy;
	q.push(p);
	while (!q.empty()) {
		p = q.front();
		q.pop();
		for (int i = 0; i < 4; i++) {
			point t;
			t.x = p.x + dir[i][0];
			t.y = p.y + dir[i][1];
			if (t.x >= 1 && t.x <= n&&t.y >= 1 && t.y <= n && !vis[t.x][t.y] && maps[t.x][t.y] != block1&&maps[t.x][t.y] != block2) {
				if (t.x == ex&&t.y == ey) {
					return true;
				}
				vis[t.x][t.y] = 1;
				q.push(t);
			}
		}
	}
	return false;
}
int main() {
	cin >> n;
	for (int i = 1; i <= n; i++) {
		for (int j = 1; j <= n; j++) {
			cin >> maps[i][j];
			if (maps[i][j] == 'S') sx = i, sy = j;
			else if (maps[i][j] == 'E') ex = i, ey = j;
		}
	}
	bool f1 = false, f2 = false;
	if (bfs('P', 'X') == true) {//两种怪物都视作障碍还能找到终点,说明满足第一种情况
		cout << "MAJOR VICTORY\n";
	}
	else{
		f1 = bfs('X', '0');//把两个怪物中的一个看做障碍
		f2 = bfs('P', '0');
		if ((f1 == false && f2 == true) || (f1 == true && f2 == false)) {//如果能找到终点则满足第二种情况
			cout << "NARROW VICTORY\n";
		}
		else cout << "LOSE\n";//否则
	}
	return 0;
}

校赛就这? 我就这。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值