首页 > 其他分享 >【LuoGu 1363】幻象迷宫——深度优先搜索 + 读题

【LuoGu 1363】幻象迷宫——深度优先搜索 + 读题

时间:2023-08-20 11:22:46浏览次数:36  
标签:WD int LuoGu 读题 迷宫 st le 1363 LHX

幻象迷宫

题目背景

(喵星人 LHX 和 WD 同心协力击退了汪星人的入侵,不幸的是,汪星人撤退之前给它们制造了一片幻象迷宫。)

WD:呜呜,肿么办啊……

LHX:momo...我们一定能走出去的!

WD:嗯,+U+U!

题目描述

幻象迷宫可以认为是无限大的,不过它由若干个 \(N\times M\) 的矩阵重复组成。矩阵中有的地方是道路,用 \(\verb!.!\) 表示;有的地方是墙,用 \(\verb!#!\) 表示。LHX 和 WD 所在的位置用 \(\verb!S!\) 表示。也就是对于迷宫中的一个点\((x,y)\),如果 \((x \bmod n,y \bmod m)\) 是 \(\verb!.!\) 或者 \(\verb!S!\),那么这个地方是道路;如果 \((x \bmod n,y \bmod m)\) 是\(\verb!#!\),那么这个地方是墙。LHX 和 WD 可以向上下左右四个方向移动,当然不能移动到墙上。

请你告诉 LHX 和 WD,它们能否走出幻象迷宫(如果它们能走到距离起点无限远处,就认为能走出去)。如果不能的话,LHX 就只好启动城堡的毁灭程序了……当然不到万不得已,他不想这么做。

输入格式

输入包含多组数据,以 EOF 结尾。

每组数据的第一行是两个整数 \(N,M\)。

接下来是一个 \(N\times M\) 的字符矩阵,表示迷宫里 \((0,0)\) 到 \((n-1,m-1)\) 这个矩阵单元。

输出格式

对于每组数据,输出一个字符串,Yes 或者 No

样例 #1

样例输入 #1

5 4
##.#
##S#
#..#
#.##
#..#
5 4
##.#
##S#
#..#
..#.
#.##

样例输出 #1

Yes
No

提示

  • 对于 \(30\%\) 的数据,\(1\le N,M\le 20\);
  • 对于 \(50\%\) 的数据,\(1\le N,M\le 100\);
  • 对于 \(100\%\) 的数据,\(1\le N,M\le 1500\),每个测试点不超过 \(10\) 组数据。

解法

看到这种迷宫类型的题目很容易想到\(DFS\)。但这题的要求又与常规的\(DFS\)题不一样,它要求判断能够从起点只向上、下、左、右四个方向前进能不能走到无穷远处。
所以,问题的关键在于如何判断能否走到无穷远处?
假设存在一条路径,能够通向无穷远处。由于迷宫是不断重复的,因此对于路径上的一个点\((x, y)\),一定能走到扩展出来的迷宫中其对应的位置\((x \,mod \,n,\,y\,mod \,m)\)。因此解决方案就呼之欲出:对坐标取模, \(\forall x \in [0, n - 1], \, y \in [0, m - 1]\),开一个三维数组\(s[x][y][3]\),其中\(s[x][y][0]\)表示\((x,y)\)是否已经访问过一次, \(st[x][y][1], st[x][y][2]\)记录上一次走到\((x, y)\)的实际坐标\((x^{'}, y^{'})\)。设当前实际坐标为\((x^{''}, y^{''})\)。如果\(x^{''} \neq x^{'} || y^{''} \neq y^{'}\),且\(st[x][y][0] == true\),则说明从一个矩阵中的某一个位置可以走到扩展出来的迷宫中的对应位置。不断重复这个过程,可以一直向外走,因此这种情况就是能够走到无穷远处的地方。
注:一定要排除走回原来位置的情况,这样只是在一个矩阵内绕圈,不算走到无穷远处。

#include<bits/stdc++.h>

const int N = 1573;

int n, m;
std::vector<std::string> g(N);
int st[N][N][3];
bool flag;

const int dx[4] = {-1, 0, 0, 1};
const int dy[4] = {0, 1, -1, 0}; 

void dfs(int x, int y, int lx, int ly) {
	if(flag) return;
	if(st[x][y][0] && (st[x][y][1] != lx || st[x][y][2] != ly)) {
		flag = true;
		return;
	}
	st[x][y][0] = true;
	st[x][y][1] = lx;
	st[x][y][2] = ly;
	for(int i = 0; i < 4; i ++ ) {
		int lxx = lx + dx[i];
		int lyy = ly + dy[i];
		int nx = (x + dx[i] + n) % n;
		int ny = (y + dy[i] + m) % m;
		if(g[nx][ny] != '#' && (st[nx][ny][1] != lxx || st[nx][ny][2] != lyy || !st[nx][ny][0])){
			dfs(nx, ny, lxx, lyy);
		}
	}
}

int main(){
	std::ios::sync_with_stdio(false);
	std::cin.tie(nullptr);
	
	while(std::cin >> n >> m) {
		memset(st, 0, sizeof st);
		flag = false;
		int sx = -1, sy = -1;
		for(int i = 0; i < n; i ++ ) {
			std::cin >> g[i];
		}

		for(int i = 0; i < n; i ++ ) {
			for(int j = 0; j < m; j ++ ) {
				if(g[i][j] == 'S'){
					sx = i;
					sy = j;
					break;
				}
			}
			if(sx >= 0 && sy >= 0) break;
		}
		dfs(sx, sy, sx, sy);
		
		if(flag) std::cout << "Yes" << '\n';
		else std::cout << "No" << '\n';
	}

	return 0;
}

标签:WD,int,LuoGu,读题,迷宫,st,le,1363,LHX
From: https://www.cnblogs.com/yjx-7355608/p/17643750.html

相关文章

  • Luogu P3369 【模板】普通平衡树 01Tire树解法
    题目传送门闲话:Luogu总共105篇题解中只有4篇01Tire树解法,虽说是非正解但未免也太少了些(貌似也不少?)……总之01Tire树的效率并不低,这道题用01Tire是很轻松的。Q:这题为什么可以用01Tire树解?能否解决一个问题,无非于三个点:可行性,空间,时间。本题要求维护一个有序数集,能进行元素修改......
  • 牛的旅行 luoguP1522 多余的换行造成的影响
    牛的旅行#include<bits/stdc++.h>usingnamespacestd;intread(){intf=1,x=0;charc=getchar();while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}while(c>='0'&&c<='9'){......
  • Luogu P9510 『STA - R3』高维立方体 题解
    题目传送门没见过这玩意,写个题解记下。题目大意周知斐波那契数列定义为:\[\operatorname{fib}(n)=\left\{\begin{aligned}1&&n\le2\\\operatorname{fib}(n-1)+\operatorname{fib}(n-2)&&n>2\end{aligned}\right.\]然后定义(\(n\le0\)函数值为\(0\))\[f(n)......
  • [Luogu P8716] 回文日期 题解
    STEP1:分析题目大意:给定一个8位数的日期,请你计算该日期之后下一个回文日期和下一个ABABBABA型的回文日期各是哪一天。这一题一眼看出是P2010的升级版,所以要先考虑到超时问题,因为如果一天一天地枚举,时间复杂度会非常高,所以我们不能直接枚举。因为题目只要"回文",所以我们只......
  • LuoguP1717 钓鱼
    题面题目分析动态规划。\(\bullet\)设计状态。思考:我从哪里来?从上一个湖过来。我到哪里去?到下一个湖去\(or\)继续在这个湖钓鱼。设\(dp[pos][tim]\)为前\(pos\)个湖花费了\(tim\)分钟所能钓的最大的鱼数量。\(\bullet\)转移状态。(为了方便计算,我们将题目中的数据......
  • [刷题笔记] Luogu P1725 琪露诺
    ProblemDescription若当前在\(pos\)位置,每次可以在\([pos+l,pos+r]\)区间内任选一个点跳。每跳到一个地方就可以获得这个地方的值,最后跳到位置\(pos\geqn\)即为结束,求如何跳才能使结束的时候获得的值最大?Analysis我们发现所有操作都是在一条链上完成的,显然若再次跳到这个位......
  • 题解 LuoguP3306 [SDOI2013] 随机数生成器
    题目链接:【LuoguP3306】。前置知识OI-Wiki:快速幂,扩展欧几里得算法(exgcd),BabyStep,GiantStep算法。题意很清楚,不说。分析当\(t=x\)时答案很明显为\(1\),即在第一天就可以读到。当\(t\neqx\)时当\(a=0\)时观察一下规律:\[x_1\equivx_1\pmod{p}\]\[x_2\equivb......
  • [刷题笔记] Luogu P1280 尼克的任务
    ProblemAnalysis首先,如果一个时间只有一个任务开始,则她必须做。如果一个时间有多个任务开始,她可以选一个去做。我们发现这样的决策是取决于后面的空暇时间,而不是前面。所以在dp的时候需要从后往前搜时间(当然如果从前往后可以跑记搜)考虑转移,如果一个时间有多个任务开始,则选一个......
  • luogu P4200 千山鸟飞绝 题解 【一维数组套平衡树】
    目录题目解题思路code题目题目链接解题思路首先,此题有明显的插入、删除、查找,所以必须要使用平衡树。考虑如何使用平衡树维护每个鸟的状态。发现很不方便,因为鸟的位置改变,整个平衡树的值都要修改。考虑针对每个节点开一颗平衡树,这样就有\(3e4\times3e4\)棵树。这显然太多了......
  • luogu P7352 炉心融解
    记\(f_S\)为所有人以当前信息推断出\(S\)这种情况是否合法,\(g_S\)表示假如真实情况是\(S\),应该有哪些人喊出来了。每一轮中,通过告诉你的\(k\)条消息可以推断出哪些集合不合法,将其\(f_S\)赋为\(0\),然后根据新的\(f_S\),有些人可能可以据此喊了,所以根据新的\(f_S\)更......