无穷迷宫
jzoj 3924
题目大意
有一个n*m的迷宫,有墙(#),路(.),和你的位置(S),这个迷宫会复制无数份拼在一起,问你能不能不停地走下去
输入样例
2
5 4
##.#
##S#
#..#
#.##
#..#
5 4
##.#
##S#
#..#
..#.
#.##
输出样例
Yes
No
样例解释
第一组测试数据中,机器人不断沿着路径向上走即可。
第二组测试数据中,机器人无论向哪个方向走都会是死路。
数据范围
50% 的数据:
100% 的数据:
解题思路
因为我们不能尝试不停的走下去,那我们想一下:
如果我们能做到不同迷宫的同一位置,那我们就可以用同样的方式再走到另一个迷宫的同一位置,那就是可以无限得走下去
那我们dfs时,保存在迷宫内的位置,也要保存对于第一个迷宫的位置,这样就可以判断是不是不同迷宫的统一个位置
代码
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define ll long long
using namespace std;
int t, n, m, x, y, ans, f[2000][2000][5];
char a[2000][2000];
const int dx[4] = {1, 0, -1, 0};
const int dy[4] = {0, 1, 0, -1};
int sx(int x)
{
return (x + n - 1) % n + 1;
}
int sy(int y)
{
return (y + m - 1) % m + 1;
}
void dfs(int x, int y, int lx, int ly)//xy是%了的lxly是没%的
{
if (f[x][y][0] && (f[x][y][1] != lx || f[x][y][2] != ly))//之前是否在别的迷宫到过这个位置
{
ans = 1;
return;
}
f[x][y][0] = 1;
f[x][y][1] = lx;
f[x][y][2] = ly;
for (int i = 0; i < 4 && !ans; ++i)
if (a[sx(x + dx[i])][sy(y + dy[i])] != '#' && (!f[sx(x + dx[i])][sy(y + dy[i])][0] || f[sx(x + dx[i])][sy(y + dy[i])][1] != lx + dx[i] || f[sx(x + dx[i])][sy(y + dy[i])][2] != ly + dy[i]))//不是同一个迷宫,或没到过且不是墙
dfs(sx(x + dx[i]), sy(y + dy[i]), lx + dx[i], ly + dy[i]);
}
int main()
{
scanf("%d", &t);
while(t--)
{
memset(f, 0, sizeof(f));
ans = 0;
scanf("%d %d", &n, &m);
for (int i = 1; i <= n; ++i)
for (int j = 1; j <= m; ++j)
{
cin>>a[i][j];
if (a[i][j] == 'S')
x = i, y = j;
}
dfs(x, y, x, y);
if (ans) printf("Yes\n");
else printf("No\n");
}
return 0;
}