P1363---幻象迷宫

题目描述

(喵星人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就只好启动城堡的毁灭程序了……当然不到万不得已,他不想这么做。。。

在这里插入图片描述

输入1
5 4
##.#
##S#
#..#
#.##
#..#
5 4
##.#
##S#
#..#
..#.
#.##
输出1
Yes
No

思路:题目的要求是看能否走出迷宫,也就是能够走到无限远处,如果走到某个点后现在又回到了这个点,则说明是可以走到无限远的.
如何进行判断是否走到过这个点呢?
每次记录取模的横纵坐标x,y,同时记录没有取模的坐标lx,ly.
lx,ly相当于是实际走时的坐标,x,y是相对于原来的地图中的坐标,因为整个大地图是原来小地图的无限扩展.
当第一次走到这个迷宫的时候,x,y和lx,ly肯定是分别相等的.
所以如果只要走到的一个点x,y和lx,ly不相等而且x,y被走过,则说明走进了两个同的小图.则这个点就是被走了两遍.
思路没啥问题,运行会出错,可能数据量太大了.之后有时间了再看看其他做法.

参考代码
#include<iostream>
#include<string.h>
using namespace std;
const int maxn = 1510;
int map[maxn][maxn],vis[maxn][maxn][3],n,m,flag;
int NEXT[4][2] = {
	0,-1,
	1,0,
	0,1,
	-1,0
};//方向数组


void dfs(int x,int y,int lx,int ly) {
	if(flag) {
		return;
	}
	if((vis[x][y][1]!=lx||vis[x][y][2]!=ly)&&vis[x][y][0]) { //结束条件 上次到这个未知的lx,ly和这次到这个位置 lx,ly不一样则说明该处已经被访问过两次了.
		flag = 1;
		return;
	}
	vis[x][y][1] = lx;
	vis[x][y][2] = ly;
	vis[x][y][0] = 1;
	for(int i = 0; i < 4; i++) {
		int xx = (x+NEXT[i][0]+n)%n;
		int yy = (y+NEXT[i][1]+m)%m;
		int lxx = lx+NEXT[i][0];
		int lyy = ly + NEXT[i][1];
		if(!map[xx][yy]) { //如果不是墙
			if(vis[lxx][lyy][1]!=lxx || vis[lxx][lyy][2] != lyy || !vis[lxx][lyy][0]) {
				dfs(xx,yy,lxx,lyy);
			}
		}
	}
}
int main() {
	ios::sync_with_stdio(false);
	char ch;
	int s_x,s_y;
	while(cin>>n>>m) {
		//数据初始化
		memset(map,0,sizeof(map));
		memset(vis,0,sizeof(vis));// 0表示道路 
		flag = 0;
		for(int i = 0; i < n; i++) {
			for(int j = 0; j< m; j++) {
				cin>>ch;
				if(ch=='#') {
					map[i][j] = 1;//表示墙  1
				}
				if(ch=='S') {
					s_x = i;
					s_y = j;
				}
			}
		}
		dfs(s_x,s_y,s_x,s_y);
		if(flag) {
			cout<<"Yes"<<endl;
		} else {
			cout<<"No"<<endl;
		}
	}
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

爱编程的大李子

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值