P1363 【幻想迷宫】

· · 题解

咳,这题卡了很久,很大原因是思路走错(看不懂题解)

具体思路:放大放大再放大,然后走到边界就传送

很明显,假如能走到之前走到过的环境相同的点(即(x mod n,y mod m)),记作A->B,那么就一定有B->同一个环境((x mod n,y mod m))的点

//同一个环境就是他的映射位置相同

细节见下面:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#define MEM(arr,num) memset(arr,num,sizeof(arr))
#define FOR(i,l,r) for(int i(l);i < r;++i)
#define SIZE 1511
using namespace std;

char board[SIZE][SIZE];
bool map1[SIZE * 2][SIZE * 2], map2[SIZE][SIZE];
//map1表示有无走到过这个点,map2表示有无走到过映射点
int n, m, dn, dm;

bool dfs(int x,int y)
{
    if(x == -1)
    {
        if(dfs(dn - 1, y))return true;
        return false;
    }
    if(x == dn)
    {
        if(dfs(0, y))return true;
        return false;
    }
    if(y == -1)
    {
        if(dfs(x, dm - 1))return true;
        return false;
    }
    if(y == dm)
    {
        if(dfs(x, 0))return true;
        return false;
    }//上面四个if表示是否到边界,是就传送
    if(map1[x][y] || board[x % n][y % m] == '#')
    {
        return false;
    }//判断能不能走
    if(map2[x % n][y % m])
    {
        return true;
    }//判断这有没有走到这个点的映射
    map1[x][y] = true;
    map2[x % n][y % m] = true;
    //记录
    if(dfs(x + 1, y))return true;
    if(dfs(x - 1, y))return true;
    if(dfs(x, y + 1))return true;
    if(dfs(x, y - 1))return true;
    //遍历
    return false;
}

int main()
{
    while(cin >> n >> m)
    {
        dn = n * 2;
        dm = m * 2;
        int sx, sy;
        FOR(i, 0, n)
        {
            FOR(j, 0, m)
            {
                cin >> board[i][j];
                if(board[i][j] == 'S')
                {
                    sx = i;
                    sy = j;
                }
            }
        }//输入+找起点
        MEM(map1, 0);
        MEM(map2, 0);
        if(dfs(sx, sy))    printf("Yes\n");
        else printf("No\n");
    }
    return 0;
}