CF196B - Infinite Maze

题目链接:

CF196B - Infinite Maze

题目大意:

给定你一个n*m的网格图,现在一个小男孩用它铺满了整个平面直角坐标系(假设有无限个这样的图)。你刚开始站在“S”这个方块上。如果一个格子是"#",你不可以走到它对应的方格。如果一个格子是".",那么你可以走到它对应的方格。所以说你可以跨越图的走动比如从一个图的(n,m)向下走,可以走到下面一个图的(1,m).你每次只可以走到相邻的格子上。

问:你所能走到的空间是否是无限的(假设无限长)。

输入:

第一行两个整数n和m,表示图的大小。

接下来n行,表示这个图。

输出:

如果路径可以达到无限长,输出"Yes";否则,输出"No".

样例一:

输入:
5 4
##.#
##S#
#..#
#.##
#..#

输出:
Yes

样例二:

输入:
5 4
##.#
##S#
#..#
..#.
#.##

输出:
No

样例分析:
样例1:可以一直重复下列动作:up up left up up right up

题目分析:

如果当前的S能够走到另一个S,那么这条路径一定是无限长的。

但是我们不想复制多几个图出来,怎么办呢?

我们考虑到,跨越图肯定是在图的边缘所以我们可以先不把跨越边的坐标变成原来的坐标,然后记录下来。如果之后再次访问到了(图内,不跨越边),那么我们会发现这和原本记录的坐标不同,就说明这个图一定存在一条无限长的路径。(DFS和BFS都可以)。

(显然不同的大佬有不同的思路)

代码实现:

//https://codeforces.com/contest/197/submission/162196583
//From yh2021ZJJ
#include<cstdio>
#include<bits/stl_pair.h>
using namespace std;
typedef pair<int,int> pii;
int n,m,sx,sy,vis[1505][1505];
char c[1505][1505];
const int dx[4]={0,1,0,-1};
const int dy[4]={1,0,-1,0};
pii from[1505][1505];
#define fi first
#define se second
bool dfs(int x,int y){
	int u=((x-1)%n+n)%n+1,v=((y-1)%m+m)%m+1;
	if(c[u][v]=='#') return 0;
	if(vis[u][v]) return from[u][v].fi!=x||from[u][v].se!=y;
	vis[u][v]=1;
	from[u][v]={x,y};
	for(int i=0;i<4;i++) if(dfs(x+dx[i],y+dy[i])) return true;
	return false;
}
int main(){
	scanf("%d%d\n",&n,&m);
	for(int i=1;i<=n;i++){
		scanf("%s",c[i]+1);
		for(int j=1;j<=m;j++) if(c[i][j]=='S') sx=i,sy=j;
	}
	if(dfs(sx,sy)) puts("Yes");
	else puts("No");
    return 0;
}

AC Code2:

//https://codeforces.com/contest/196/submission/5996948
//From HIR180
#include<bits/stdc++.h>
using namespace std;
char f[1505][1505];
bool used[1505][1505];
int pre[1505][1505][2];
int h,w,dx[4]={-1,0,1,0},dy[4]={0,-1,0,1};
bool dfs(int x,int y){
	int nx=((x%h)+h)%h;
	int ny=((y%w)+w)%w;
	if(f[nx][ny]=='#') return 0;
	int &zx=pre[nx][ny][0];
	int &zy=pre[nx][ny][1];
	if(used[nx][ny]) return mp(zx,zy)!=mp(x,y);
	zx=x,zy=y,used[nx][ny]=true;
	for(int i=0;i<4;i++) if(dfs(x+dx[i],y+dy[i])) return 1;
	return 0;
} 
int main(){
	scanf("%d%d",&h,&w);
	for(int i=0;i<h;i++) scanf("%s",&f[i]);
	int sx,sy;
	bool ok=false;
	for(int i=0;i<h;i++) for(int j=0;j<w;j++) if(f[i][j]=='S') ok=dfs(i,j);
	puts(ok?"YES":"NO");
	return 0;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值