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";
}
}
此生无悔入OI 来生AK IOI

浙公网安备 33010602011771号