CF197D Infinite Maze 解题报告

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 x1,y),( x , y − 1 x,y-1 x,y1),( x + 1 , y x+1,y x+1,y),( x , y + 1 x,y+1 x,y+1)),前提是他将要渠道的单元格可以通行(不是墙)。

输入格式

第一行包含两个空格分隔的整数nm迷宫的高度和宽度,男孩用来周期性地在平面上平铺。

接下来 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;
}
  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值