(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;
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值