洛谷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。
原题链接


Input

5 4
##.#
##S#
#..#
#.##
#..#
5 4
##.#
##S#
#..#
..#.
#.##
7 6
##.#.#
##.#.#
##.S.#
######
##...#
##.#.#
##.#.#

Output

Yes
No
No

解题思路

整个迷宫是由 N*M 小迷宫无限扩展形成的,想要走到无限远的地方,那就应该走出很远后,又能到达某个走过的点(这个走过是指,相对小迷宫的位置已经被走过了)
图片
所以我们就可以沿着这条路径无限的走下去,注意,如果是小迷宫内部一条路径自成环的话,沿着环一直走是不可以的。所以我们的任务是,判断这个点在其它小迷宫里面是否被走过,怎么判断呢,设(x,y)为到达某一点的坐标,当(x,y)超出小迷宫的边界时,我们可以对其取模,我们可以记录下到达(x,y)时的真实坐标(lx,ly)(即不取模的坐标),并记录这(x,y)已经走过,当再次走到(x,y)时,对比此时的真实坐标与原来存储的,只要不相同,则说明我们找到可以无限重复走的路径,输出 Yes


AC代码

#include <iostream>
#include <queue>
#include <cstring>
using namespace std;

const int N = 1510;
const int dx[4] = {-1,0,0,1},dy[4] = {0,-1,1,0};
bool Map[N][N],flag; // Map记录小迷宫哪些点时可以走的,flag记录是否找到答案
int n,m,sx,sy,mark[N][N][3];// (sx,sy)为出发点,mark[x][y][0]记录到达小迷宫中
char c;// (x,y)点时的真实 x 坐标,mark[x][y][1],记录真实 y 坐标,mark[x][y][2] 记录是否走过

void dfs (int x,int y,int lx,int ly){
    if(flag) return ;
    if(mark[x][y][2] && (mark[x][y][1] != lx || mark[x][y][0] != ly)){
        flag = 1; // 如果已经走过,且这次的真实坐标跟上次记录的不同,就找到答案了
        return ;
    }
    mark[x][y][0] = lx,mark[x][y][1] = ly,mark[x][y][2] = 1;
    for(int i = 0; i < 4; i++){
        int xx = (x + dx[i] + n) % n,yy = (y + dy[i] + m) % m;
        int lxx = lx + dx[i],lyy = ly + dy[i];
        if(Map[xx][yy]){ //如果这个点可以走
            if(mark[xx][yy][0] != lxx || mark[xx][yy][1] != lyy || !mark[xx][yy][2])
//这步判断是为了避免往回走
                dfs(xx,yy,lxx,lyy);
        }
    }
}

int main(){
    ios::sync_with_stdio(false);
    cin.tie(0),cout.tie(0);
    while(cin >> n >> m){
        memset(Map,0,sizeof(Map));
        memset(mark,0,sizeof(mark));
        flag = false;
        for(int i = 0; i < n; i++)
            for(int j = 0; j < m; j++) {
                cin >> c;
                if(c != '#') Map[i][j] = 1;
                if(c == 'S') sx = i,sy = j;
            }
        dfs(sx,sy,sx,sy);
        if(flag) puts("Yes");
        else puts("No");
    }
    return 0;
}
posted @ 2021-09-03 16:19  伍六柒-  阅读(150)  评论(0编辑  收藏  举报