前言
个人感觉比较有意思的一道题,思路还是挺巧妙的,到了lydd那里就变成中规中矩的题了
题目描述
由于tyx抱过了这么多大腿,他变得越来越棒棒了,一般的迷宫根本拦不住他。为了治一治他,你决定为他单独定制一款无限迷宫。
所谓无限迷宫是指,由一个 的迷宫单元经过无限平铺得到的迷宫,即将无数份迷宫单元平铺在一个二维平面上。定制好以后,你将tyx扔到了迷宫里,不妨假定tyx落在了起点处。
出于对无限迷宫的恐惧,tyx想要尽可能逃离这里。那么问题来了,tyx能不能逃到距离起点无限远的地方去呢?
输入格式
第一行两个整数 ,用来描述迷宫单元的尺寸。
接下来是一个 的字符矩阵,用来描述这个迷宫,每个字符一定属于以下三种:
字符’.'代表这个点是空地。
字符’S’代表这个点是起点。
字符’#'代表这个点是墙,不可以走。
输出格式
输出一行一个字符串“Yes”或“No”(不包括引号),“Yes”表示tyx可以逃到无限远的地方,“No”表示不可以。
样例
样例输入1
3 3
#.#
#.#
#S#
样例输出1
Yes
样例输入2
5 5
#.#.#
…#.S
…#…
#.#.#
样例输出2
No
一开先我的思路是就在图里跑,到了边界如果对边有对应的入口就穿越到那里,如果最后回到起点就说明不行
但这个思路在第一个样例就过不去了,再考虑一下文中说的"无限"两字,发现只要最后到达在初始迷宫中同一个位置时,不是初始地图就可以逃脱,因为它可以用相同的路线跑到下一个此位置,然后无限远离起点
定义每个位置的坐标为x,y,bx,by,其中bx和by表示以初始地图为参照物的其他地图的位置,用bix数组和biy数组存下每个初始地图中的点的坐标,进行比较就行了
code:
#include<cstdio>
#include<iostream>
#include<queue>
using namespace std;
int sx,sy,n,m,bix[2005][2005],biy[2005][2005];
char mp[2005][2005];
bool vis[2005][2005];
const int dx[]={1,-1,0,0};
const int dy[]={0,0,1,-1};
struct ren{
int x,y,bx,by;
}st;
queue<ren> q;
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
cin>>mp[i][j];
if(mp[i][j]=='S')
{
sx=i;
sy=j;
}
}
}
st.x=sx;
st.y=sy;
q.push(st);
while(!q.empty())
{
ren now=q.front();
q.pop();
for(int i=0;i<4;i++)
{
ren b=now;
int nowx=b.x+dx[i],nowy=b.y+dy[i];
//边界处理
if(nowx>m)
{
nowx-=n;
b.bx++;
}
else if(nowx==0)
{
nowx+=n;
b.bx--;
}
else if(nowy>n)
{
nowy-=m;
b.by++;
}
else if(nowy==0)
{
nowy+=m;
b.by--;
}
b.x=nowx;
b.y=nowy;
if(mp[nowx][nowy]=='#')
{
continue;
}
if(!vis[nowx][nowy])
{
vis[nowx][nowy]=1;
bix[nowx][nowy]=b.bx;
biy[nowx][nowy]=b.by;
q.push(b);
}
else if(b.bx!=bix[nowx][nowy]||b.by!=biy[nowx][nowy])
{
printf("Yes\n");
return 0;
}
}
}
printf("No\n");
return 0;
}