洛谷 P1363 幻想迷宮 解題報告
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 幻想迷宮 解題報告