(bfs)洛谷P1363幻象迷宫

洛谷P1363幻象迷宫

思路:

刚开始,我的思路是能够再次找到S点,就能无限走下去。
然而看反例:

5 5
#####
#...#
#.#S#
#...#
#####

很显然,这不能走出去。

5 5
#####
..#..
#S#.#
..#..
#####

与第一个样例相似。
那么又想到走到的不是本来的S,而是其他图的S。然后就想是不是两层就可以了,他本身是在第一层,然后到边上后就到了第二层。
然而又是全部WA。QAQ。
看反例:

5 5
#..##
#S###
..##.
##...
##.##

他显然可以不断向左向下走无穷远,但我们可以发现,他不能在“下一层”到达S点,他是在“第三层”的时候才到了S点。然后试了试三层……
所以我们拓宽一下思路,我们要找到不是可以到下一个S点。而是,只要我们能第二次经过相对位置相同的一个点,那么我们就可以无限次的经过这个相对点以走到无穷远处。
那么怎么判断走到这一点是之前经过的点还是相对位置上的点呢?
看了大佬的题解,才明白,我们这里用vis数组存的不只是有没有经过(x%n,y%m)点,而是存了hash(x,y),来判断他到的是原本就走过的点还是相对位置相同的点。相对位置相同但是hash值不同即可说明第二次经过某个相对位置相同的点,就表示可以无限走下去。

代码:

#include<bits/stdc++.h>
#define pii pair<int,int>
#define ll long long
#define cl(x) memset(x,0,sizeof(x))
#define ct cerr<<"Time elapsed:"<<1.0*clock()/CLOCKS_PER_SEC<<"s.\n";
const int N=1e6+10;
const int mod=1e3+7;
const int maxn=0x3f3f3f3f;
const int minn=0xc0c0c0c0;
const int inf=99999999;
using namespace std;
char maze[1600][1600];
int vis[1600][1600],n,m,dis[4][2]={{1,0},{-1,0},{0,1},{0,-1}}; 
struct edge
{
	int x,y;
}be;
int ha(int x,int y)
{
	return ((x*131+y*1331)%mod+mod)%mod;
}
int bfs()
{
	queue<edge> q;
	q.push(be);
	vis[be.x][be.y]=ha(be.x,be.y);
	edge temp,pre,k;
	while(!q.empty())
	{
		int i;
		pre=q.front();
		q.pop();
		for(i=0;i<4;i++)
		{
			temp.x=pre.x+dis[i][0];
			temp.y=pre.y+dis[i][1];
			int h=ha(temp.x,temp.y);
			k.x=(temp.x+10*n)%n;
			k.y=(temp.y+10*m)%m;
			if(maze[k.x][k.y]=='#')	
				continue;
			if(!vis[k.x][k.y])
			{
				q.push(temp);
				vis[k.x][k.y]=h;
			}
			else if(vis[k.x][k.y]!=h)
				return 1;
		}
	}
	return 0;
}
int main()
{
	while(~scanf("%d%d",&n,&m))
	{
		int i,j;
		for(i=0;i<n;i++)
			scanf("%s",maze[i]);
		cl(vis);
		for(i=0;i<n;i++)
			for(j=0;j<m;j++)
			{
				if(maze[i][j]=='S')
				{
					be.x=i;
					be.y=j;
					break;
				}
			}
		int p=bfs();
		if(p)	printf("Yes\n");
		else printf("No\n");
	}
	return 0;
}

发布了119 篇原创文章 · 获赞 1 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/Z7784562/article/details/104119410
今日推荐