CF197D Infinite Maze 解题报告
1 题目链接
2 题目翻译
题目:无限的迷宫
题目描述
现在有一个 n × m n\times m n×m的一个长方形迷宫。其中每个单元格要么可以通行,要么不行(是一堵墙)。一个小男孩发现了迷宫,并用它周期性地铺了一个平面,使平面变成了一个无限的迷宫。现在在这个平面单元格( x , y x,y x,y)是一堵墙。
现在这个男孩站在无限迷宫上的某个单元格前,他想知道自己是否能从起始位置走到无限远的地方。从坐标为( x , y x,y x,y)的单元格它可以去到他四周的单元格(( x − 1 , y x-1,y x−1,y),( x , y − 1 x,y-1 x,y−1),( x + 1 , y x+1,y x+1,y),( x , y + 1 x,y+1 x,y+1)),前提是他将要渠道的单元格可以通行(不是墙)。
输入格式
第一行包含两个空格分隔的整数n
和m
迷宫的高度和宽度,男孩用来周期性地在平面上平铺。
接下来
n
n
n行中的每一行都包含
m
m
m个字符——对于单位迷宫的描述。每个字符要么是一个#
,表示一堵不可通过(墙);要么是一个.
,这标志着一个可通过的单位格子;或是S
,标志着小男孩的起点。
输出格式
如果小男孩能从起点走到无限远,请输出Yes
。否则,输出No
。
样例输入1
5 4
##.#
##S#
#..#
#.##
#..#
样例输出1
Yes
样例输入2
5 4
##.#
##S#
#..#
..#.
#.##
样例输出2
No
数据范围
对于100%的数据:
n , m ∈ [ 1 , 1500 ] n,m\in[1,1500] n,m∈[1,1500]
3 题目分析
3.1题目大意
有一个由已给出的地图周期性铺成的无限的迷宫,问出发点S
是否处于一个不封闭的空间。
3.2样例分析
如上所述。
4 解法分析
只需要判断有S
出发的能否到达向团队位置不变的同一点。若能,由周期性即可知S
处于一个不封闭空间,输出Yes
;若不能,输出No
即可。
于是,该题就成了一道简单的搜索题。
5 AC代码
AC code #001
//https://codeforces.com/contest/197/submission/69734355
//Fron : Normie28
//Rating : 2453
#define _CRT_SECURE_NO_WARNINGS
#include <bits/stdc++.h>
using namespace std;
void fast()
{
std::ios_base::sync_with_stdio(0);
cin.tie(NULL); cout.tie(NULL);
}
int n, m, si, sj;
vector<vector<int>> v;
map<pair<int, int>, int > mp;
int vis[2000][2000];
char a[2000][2000];
bool b = 0;
void dfs(int i,int j)
{
if ( b ) return;
int ii, jj;
ii = i, jj = j;
while (i < 0) i += n;
while (j < 0) j += m;
if (i >= n) i %= n;
if (j >= m) j %= m;
if ( vis[i][j] && mp[{ii, jj}] == 0)
{
b = 1;
return;
}
if (vis[i][j] || a[i][j] == '#') return;
vis[i][j] = 1;
mp[{ii, jj}] = 1;
dfs(ii, jj + 1);
dfs(ii, jj - 1);
dfs(ii + 1, jj);
dfs(ii - 1, jj);
}//十分朴素的一个dfs
int main()
{
fast();
cin >> n >> m;
for (int i = 0;i < n;i++)
for (int j = 0;j < m;j++)
{
cin >> a[i][j];
if (a[i][j] == 'S') si = i, sj = j;
}
v.resize(n + 2);
mp[{si, sj}] = 1;
dfs(si, sj);
if (b) cout << "Yes" << endl;
else cout << "No" << endl;
}
AC code #002
//https://codeforces.com/contest/197/submission/36227081
//From : step_by_step
//Rating : 2828
#include <stdio.h>
#include <bits/stdc++.h>
#define uint unsigned int
#define ll long long
#define ull unsigned long long
#define ld long double
#define rep(i, l, r) for (int i = l; i < r; i++)
#define repb(i, r, l) for (int i = r; i > l; i--)
#define sz(a) (int)a.size()
#define fi first
#define se second
#define mp(a, b) make_pair(a, b)
using namespace std;
const int N = 1500;
const int inf = (int)1e9 + 1;
const ll big = (ll)1e18 + 1;
const int P = 239;
const int MOD = (int)1e9 + 7;
const int MOD1 = (int)1e9 + 9;
const double eps = 1e-9;
const double pi = atan2(0, -1);
const int ABC = 26;
vector<int> dx = {0, 0, -1, 1};
vector<int> dy = {-1, 1, 0, 0};
int n, m;
string a[N];
bool used[N][N];
int comp[N][N];
void dfs(int x, int y, int c)
{
used[x][y] = true;
comp[x][y] = c;
rep(i, 0, 4)
if (x + dx[i] >= 0 && x + dx[i] < n && y + dy[i] >= 0 && y + dy[i] < m && a[x + dx[i]][y + dy[i]] != '#' && !used[x + dx[i]][y + dy[i]])
dfs(x + dx[i], y + dy[i], c);
}
vector<pair<int, int> > gx[N * 4], gy[N * 4];
bool check(int n, int s)
{
int d[n], D[n];
fill(d, d + n, inf);
fill(D, D + n, -inf);
d[s] = D[s] = 0;
rep(t, 0, n)
{
bool flag = false;
rep(u, 0, n)
{
if (d[u] == inf || D[u] == -inf)
continue;
for (auto &v : gx[u])
{
if (d[u] + v.se < d[v.fi])
{
d[v.fi] = d[u] + v.se;
flag = true;
}
if (D[u] + v.se > D[v.fi])
{
D[v.fi] = D[u] + v.se;
flag = true;
}
}
}
if (t == n - 1)
return flag;
}
}
int main()
{
ios_base::sync_with_stdio(0);
cin.tie(0);
cout.precision(20);
cin >> n >> m;
rep(i, 0, n)
cin >> a[i];
int c = 0;
rep(i, 0, n)
rep(j, 0, m)
if ((i == 0 || i == n - 1 || j == 0 || j == m - 1) && a[i][j] != '#' && !used[i][j])
dfs(i, j, c++);
int sx, sy;
rep(i, 0, n)
rep(j, 0, m)
if (a[i][j] == 'S')
{
sx = i;
sy = j;
}
if (!used[sx][sy])
{
cout << "No\n";
return 0;
}
rep(x, 0, n)
rep(y, 0, m)
if ((x == 0 || x == n - 1 || y == 0 || y == m - 1) && a[x][y] != '#')
{
rep(i, 0, 4)
if (x + dx[i] < 0 || x + dx[i] >= n || y + dy[i] < 0 || y + dy[i] >= m)
{
int x1 = (x + dx[i] + n) % n, y1 = (y + dy[i] + m) % m;
if (a[x1][y1] != '#')
{
gx[comp[x][y]].push_back({comp[x1][y1], dx[i]});
gy[comp[x][y]].push_back({comp[x1][y1], dy[i]});
}
}
}
if (check(c, comp[sx][sy]))
{
cout << "Yes\n";
return 0;
}
rep(i, 0, c)
gx[i] = gy[i];
if (check(c, comp[sx][sy]))
{
cout << "Yes\n";
return 0;
}
cout << "No\n";
return 0;
}
AC code #003
//https://codeforces.com/contest/197/submission/28735384
//From : cxt
//Rating : 2416
//代码简洁 思路清晰
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstdlib>
#include<queue>
using namespace std;
const int N=1510,dx[]={0,0,1,-1},dy[]={1,-1,0,0};
int n,m,sx,sy,vis[N][N],wx[N][N],wy[N][N],mp[N][N];
char s[N];
inline bool dfs(int x,int y){
int u=((x-1)%n+n)%n+1,v=((y-1)%m+m)%m+1;
if (mp[u][v]) return 0;
if (vis[u][v]) return wx[u][v]!=x||wy[u][v]!=y;
vis[u][v]=1;wx[u][v]=x;wy[u][v]=y;
for (int i=0;i<4;++i) if (dfs(x+dx[i],y+dy[i])) return 1;
return 0;
}
int main(){
while (scanf("%d%d",&n,&m)>0){
for (int i=1;i<=n;++i){
scanf("%s",s+1);
for (int j=1;j<=m;++j){
if (s[j]=='S') sx=i,sy=j;
mp[i][j]=(s[j]=='#');
wx[i][j]=wy[i][j]=vis[i][j]=0;
}
}
puts(dfs(sx,sy)?"Yes":"No");
}
return 0;
}