zoukankan      html  css  js  c++  java
  • 洛谷P1363-幻想迷宫

    Problem 洛谷P1363-幻想迷宫

    Accept: 1.1k   Submit: 6.1k
    Time Limit: 1000 mSec    Memory Limit : 128MB

    Problem Description

    背景 Background

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

    WD:呜呜,肿么办啊……

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

    WD:嗯,+U+U!

    描述 Description

    幻象迷宫可以认为是无限大的,不过它由若干个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就只好启动城堡的毁灭程序了……当然不到万不得已,他不想这么做。。。

     Input

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

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

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

     Output

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

     Sample Input

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

    Sample output

    Yes
    No
     

    说明

    数据范围和注释 

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

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

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

     
    题目链接:https://www.luogu.org/problemnew/show/P1363

    题解:这个题还是挺有意思的,第一反应是DFS搜一下联通块,看边界,如果边界有对称的能到达的,肯定能无限走下去,然后很愉快地WA了......

    上述判据充分不必要,虽然不对,但是还是给接下来的做法提供了思路,画个图就知道为啥不对,把这个迷宫复制成3*3(我画的时候画的是2*2),比如向右到达一个扩展的迷宫,这个时候再到达下面的扩展的的迷宫,和从原始迷宫到达下面的扩展来的迷宫肯定是不一样的,怎么解决这个冲突,最原始的想法是给这9个迷宫编上号,vis数组标记不同的迷宫,如果一个在取模意义下相同的格子被标记了不同的编号,那就肯定可以走无限远,但是这样实现起来很不方便,导致代码贼长,看了别人的题解,发现了一个非常机智的做法,vis数组加一维,最后一维只有0、1、2,0用来记录有没有到达过,1、2分别记录没有取模的横纵坐标,每次向四周延伸的时候,如果还没有被遍历过,那就是普通的标记,如果已经被遍历过,那就比较当前未取模的坐标和这个点记录的未取模坐标是否相同,相同就代表着是在同一个迷宫第二次遇到,忽略,不同就代表着在不同的迷宫遇到了同一个格子,自然能够走无限远。

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <cstring>
     4 #include <cstdlib>
     5 using namespace std;
     6 
     7 const int maxn = 1500+10;
     8 int n,m;
     9 int sx,sy;
    10 int dir[4][2] = {{1,0},{-1,0},{0,1},{0,-1}};
    11 char gra[maxn][maxn];
    12 int vis[maxn][maxn][3];
    13 bool flag;
    14 
    15 void dfs(int x,int y){
    16     if(flag) return;
    17     int xx,yy,r,c;
    18     for(int i = 0;i < 4;i++){
    19         xx = vis[x][y][1]+dir[i][0],yy = vis[x][y][2]+dir[i][1];
    20         r = (x+dir[i][0]+n)%n,c = (y+dir[i][1]+m)%m;
    21         if(gra[r][c] != '#'){
    22             if(!vis[r][c][0]){
    23                 vis[r][c][0] = 1;
    24                 vis[r][c][1] = xx,vis[r][c][2] = yy;
    25                 dfs(r,c);
    26             }
    27             else{
    28                 if(vis[r][c][1]!=xx || vis[r][c][2]!=yy){
    29                     flag = true;
    30                     return;
    31                 }
    32             }
    33         }
    34     }
    35 }
    36 
    37 int main()
    38 {
    39     //freopen("input.txt","r",stdin);
    40     while(~scanf("%d%d",&n,&m)){
    41         memset(vis,0,sizeof(vis));
    42         flag = false;
    43         for(int i = 0;i < n;i++){
    44             scanf("%s",gra[i]);
    45             for(int j = 0;j < m;j++){
    46                 if(gra[i][j] == 'S') gra[i][j]='.',sx = i,sy = j;
    47             }
    48         }
    49         vis[sx][sy][0] = 1;
    50         vis[sx][sy][1] = sx,vis[sx][sy][2] = sy;
    51         dfs(sx,sy);
    52         if(!flag) printf("No
    ");
    53         else printf("Yes
    ");
    54     }
    55     return 0;
    56 }
  • 相关阅读:
    mysql 触发器 插入
    【经验】STL的list vector在iterator迭代器的循环中 使用erase 造成的BUG
    C/C++ 关于 for循环 的第二个表达式右侧非常量的时候
    MySQL C API的一个让我头疼的问题,获得一行记录中包括NULL
    vim粘贴代码的时候,恶心的缩进.
    [转]分析MySQL数据类型的长度【mysql数据字段 中length和decimals的作用!熟悉mysql必看】
    [转]对于孩子:旅行的意义何在?
    libc中的标准函数 localtime和localtime_r 的用法
    【腾讯面试题目】非循环方式 计算一个32位整数中被置1的位数
    C++对带有分隔符的字符串 分割为数字的通用解决方案
  • 原文地址:https://www.cnblogs.com/npugen/p/9498233.html
Copyright © 2011-2022 走看看