• P1363 幻象迷宫


    题意:给你一个nxm的迷宫g(x,y范围是0~n - 1和0~m - 1),‘#’不能走,‘.’可以走,'S'作为起点,现在将迷宫扩展成无穷大,扩展方法是:任意一个(x, y)位置的字符c = g(x % n, y % m),现在问你可不可以从起点处走到无穷远处。

    例子:

    原始迷宫5x5为中间的黄色区域,标红色的位置的坐标为(-2, -4), 而 (-2) % 5 = 3, (-4) % 5 = 1, 所以(-2, 4)位置处,应该和g(3, 1)相同,所以为S。

    思路:对于一个位置A(x, y)如果能够走到另一个位置B(p, q), A≠B,并满足A和B在对应的nxm图中的相对位置相同(意思是:p % n = x % n, q % m = y % m),那么不断重复这个过程,就一定能走到无穷远处。所以考虑从起点(位于原图中,扩展的图中的其他S看成是‘.’)开始dfs(此处是flood fill),一旦两次都遍历到了原图上的同一位置,并且这两次遍历到的点不同,那么说明可以走到无穷远处,否则不能。

    注意红色部分:假设两次遍历到的点为(x,y)和(p,q), 那么遍历到原图上的同一位置指的是p % n = x % n, q % m = y % m(是就相对位置而言的)

    一开始我是每遍历到一个点(x, y)就对原图上的(x % n, y % m)标记访问过,然后在后面的遍历过程中一旦发现一个位置(p, q)有(p % n, q % m)已经被访问过,那么就认为能够走到无穷远,这是错的,因为有可能(x, y)和(p, q)是同一个点。

    由于模运算的不可逆,意思就是说,如果只是简单的在访问到(x,y)时,对(x % n,y % m)标记已访问,那么在下一次搜索到某点(p, q)时就算(p % n,q % m)恰好为(x, y)标记过的地方,也不能肯定(p, q)和(x, y)不是同一点,所以有必要对于原图中的每一个位置(u, v)保存一下第一次访问到它(指x % n = u, y % m = v)的坐标(x, y)

    由于涉及到负数取模,所以还得自己写一下取模函数。

    #include<iostream>
    #include<cstring>
    
    using namespace std;
    
    const int N = 1510;
    
    int n, m;
    char g[N][N];
    int st[N][N][3]; // st[u][v][0~2]分别表示:是否访问过,x和y
    int dx[] = {0, 1, 0, -1}, dy[] = {1, 0, -1, 0};
    
    int mod(int a, int b){
        if(a >= 0) return a % b;
        return ((-a / b + 1) * b + a) % b;
    }
    
    int dfs(int x, int y){
        
        for(int i = 0; i < 4; i ++){
            int a = x + dx[i], b = y + dy[i];
            int ma = mod(a, n), mb = mod(b, m);
            
            if(g[ma][mb] == '#') continue;
            if(st[ma][mb][0]){
                if(st[ma][mb][1] != a || st[ma][mb][2] != b) return 1;
                continue;
            }
            
            st[ma][mb][0] = 1, st[ma][mb][1] = a, st[ma][mb][2] = b;
            if(dfs(a, b)) return 1;
        }
        
        return 0;
    }
    
    int main(){
        while(cin >> n >> m){
            memset(st, 0, sizeof st);
            
            int x, y;
            for(int i = 0; i < n; i ++)
                for(int j = 0; j < m; j ++){
                    cin >> g[i][j];
                    if(g[i][j] == 'S') x = i, y = j;
                }
            
            st[x][y][0] = 1, st[x][y][1] = x, st[x][y][2] = y;
            
            if(dfs(x, y)) cout << "Yes" << endl;
            else cout << "No" << endl;
        }
        
        return 0;
    }
    
  • 相关阅读:
    再谈TextField
    IOS-TextField知多少
    leftBarButtonItems
    LeftBarButtonItems,定制导航栏返回按钮
    Apple Mach-O Linker (id) Error "_OBJC_CLASS...错误解决办法 Apple Mach-O Linker (id) Error "_OBJC_CLASS...错误解决办法
    Unrecognized Selector Sent to Instance问题之诱敌深入关门打狗解决办法
    UNRECOGNIZED SELECTOR SENT TO INSTANCE 问题快速定位的方法
    Present ViewController,模态详解
    UILABEL AUTOLAYOUT自动换行 版本区别
    iOS自动布局解决警告Automatic Preferred Max Layout Width is not available on iOS versions prior to 8.0
  • 原文地址:https://www.cnblogs.com/tomori/p/14320956.html
Copyright © 2020-2023  润新知