1. 程式人生 > >洛谷 P1363 幻想迷宮 解題報告

洛谷 P1363 幻想迷宮 解題報告

clu 上下左右 不想 單元 work 報告 一個點 lse sca

P1363 幻想迷宮

題目描述

背景 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就只好啟動城堡的毀滅程序了……當然不到萬不得已,他不想這麽做。。。

輸入輸出格式

輸入格式:

輸入格式 InputFormat

輸入包含多組數據,以EOF結尾。

每組數據的第一行是兩個整數N、M。

接下來是一個N*M的字符矩陣,表示迷宮裏(0,0)到(n-1,m-1)這個矩陣單元。

輸出格式:

輸出格式 OutputFormat

對於每組數據,輸出一個字符串,Yes或者No。

說明

數據範圍和註釋 Hint

對於30%的數據,N,M<=20

對於50%的數據,N.M<=100.

對於100%的數據,N,M<=1500,每個測試點不超過10組數據.


神仙題。。

我們考慮怎麽才算可以走無窮

我一開始的想法是找到把連通塊求出來,然後通過邊界之間的連接以連通塊為點建立無向圖,看看起點在的連通塊有沒有與一個環連接

然後我就涼了

比如這個

#.#.#
..#..
#####
.S#..
#.#.#

好吧我不是很懂於是去看題解了

結果是某一個點可以走到它在別的圖的它自己就行,但走到它自己圖上的它自己就不行。

好像是那麽回事呢。

然後我們用一種比較神仙的方法記錄

\(used[i][j][0/1/2]\)前兩維普通的used數組,後一位0表示可達,1表示上一次走到這個點的\(x\)坐標,2表示上一次走到這個點的\(y\)坐標

註意下標\(i,j\)存儲的是坐標對原圖的映射,而後面表示的是真實坐標

\(dfs\)時代入四個參數分別表示當前坐標映射和當前實際坐標


Code:

#include <cstdio>
#include <cstring>
const int N=1502;
char g[N][N];
int used[N][N][3],n,m,sx,sy,flag;
const int dx[5]={0,-1,0,1,0};
const int dy[5]={0,0,1,0,-1};
void dfs(int x,int y,int qx,int qy)
{
    if(used[x][y][0]&&(used[x][y][1]!=qx||used[x][y][2]!=qy))
        flag=1;
    if(used[x][y][0]) return;
    if(flag) return;
    used[x][y][1]=qx,used[x][y][2]=qy,used[x][y][0]=1;
    for(int i=1;i<=4;i++)
    {
        int tox=(x+dx[i]+n)%n,toy=(y+dy[i]+m)%m;
        if(g[tox][toy]!=‘#‘)
            dfs(tox,toy,qx+dx[i],qy+dy[i]);
    }
}
void work()
{
    flag=0;
    memset(used,0,sizeof(used));
    for(int i=0;i<n;i++)
    {
        scanf("\n");
        for(int j=0;j<m;j++)
        {
            scanf("%c",&g[i][j]);
            if(g[i][j]==‘S‘)
                sx=i,sy=j;
        }
    }
    dfs(sx,sy,sx,sy);
    if(flag) printf("Yes\n");
    else printf("No\n");
}
int main()
{
    while(scanf("%d%d",&n,&m)!=EOF)
        work();
    return 0;
}

2018.7.27

洛谷 P1363 幻想迷宮 解題報告