P1363

幻象迷宫

题目描述

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

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

输入格式

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

每组数据的第一行是两个整数N、M。

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

输出格式

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

样例 #1

样例输入 #1

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

样例输出 #1

Yes
No

提示

对于30%的数据,N,M<=20

对于50%的数据,N.M<=100.

对于100%的数据,N,M<=1500,每个测试点不超过10组数据.

好题
如何判断能否走出无限大的?
之前做过能否走到无限大的地图上的每一个点
而这道题需要判断的是能否走了后取模回到以前走过的点 即有一个循环通路
细节很多:
四个参数 x y xx yy
x y是每次取模后的坐标  xx yy是永远不取模的坐标 即走到无限远的实际坐标
我们用vis[x][y][0]:是否到过(x,y)(mod) vis[x][y][1]:第一次到的x坐标 vis[x][y][2]:第一次到的y坐标
如果我们搜索到某次dfs(x,y,xx,yy)发现 vis[x][y][0]==1且(xx,yy)!=(vis[x][y][1],vis[x][y][2]) 那么就说明循环了
点击查看代码
#include<bits/stdc++.h>
using namespace std;
int n,m,sx,sy,flag;
int vis[1505][1505][3];
char a[1505][1505];
int dx[4]= {1,0,-1,0};
int dy[4]= {0,1,0,-1};
void dfs(int x,int y,int xx,int yy) {
	if(vis[x][y][0]&&(vis[x][y][1]!=xx||vis[x][y][2]!=yy)) {
		flag=1;
		return ;
	}
	vis[x][y][0]=1;
	vis[x][y][1]=xx,vis[x][y][2]=yy;
	for(int i=0; i<4; i++) {
		int mx=(x+dx[i]+n)%n,my=(y+dy[i]+m)%m;
		int nx=xx+dx[i],ny=yy+dy[i];
		if(a[mx][my]=='#')continue;
		if(vis[mx][my][1]!=nx||vis[mx][my][2]!=ny||!vis[mx][my][0])
			dfs(mx,my,nx,ny);
		if(flag)return ;
	}
	if(flag)return ;
}
int main() {
	ios::sync_with_stdio(false);
	while(cin>>n>>m) {
		flag=0;
		memset(vis,0,sizeof(vis));
		for(int i=0; i<n; i++)
			for(int j=0; j<m; j++) {
				cin>>a[i][j];
				if(a[i][j]=='S')
					sx=i,sy=j;
			}
		dfs(sx,sy,sx,sy);
		if(flag)cout<<"Yes\n";
		else cout<<"No\n";
	}
}
posted @ 2023-01-26 11:33  PKU_IMCOMING  阅读(38)  评论(0)    收藏  举报