CF540C Ice Cave 解题报告

CF540C Ice Cave 解题报告

1 题目链接

传送门

2 题目大意

2.1 题目 : 冰洞(直译)
2.2 题目大意 :

现在有一个 n × m n\times m n×m的一个矩阵,其中的元素是X.。现在,你从坐标为( r 1 r_1 r1, c 1 c_1 c1)的点出发(该点为X),要到达坐标为( r 2 r_2 r2, c 2 c_2 c2)的点(该点可能为X.且可能与出发点重合)。其中,元素为x的点不能走(除出发外);元素为.的点在走过一次后变为x。问 : 你能否到达终点并此时终点元素为X

3 解法分析

3.1 方法一 :

凭借多年的搜索经验,该题可以直接 b f s bfs bfs(广度优先搜索)或 d f s dfs dfs(深度优先搜索)+特判 解决。但代码量想来不会太少,在此不做过多赘述。

3.2 方法二 :

本蒟蒻首先想到方法一,这种极具小奥特征的方法还是在Dalao代码以及大佬@MYi_Qn 的帮助之下理解的。
经过三个样例的鞭策,不难发现,若第一次已经走到了( r 2 r_2 r2, c 2 c_2 c2)上的话,只要周围还有一个格子能走,就一定可以成功[( r 2 r_2 r2, c 2 c_2 c2)]上元素为X暴搜即可。
那么,不妨先将周围的一块格子先保护起来,然后再跑一遍 b f s bfs bfs只要走得到( r 2 r_2 r2, c 2 c_2 c2),那就一定可以第二次到达( r 2 r_2 r2, c 2 c_2 c2)

4 AC代码

4.1 Dalao代码 #001
// From realcomplex
// Rating 2401
#include <bits/stdc++.h>

using namespace std;

const int N = 505;
int conf[N][N];

void ini(){
	for(int i = 0;i<N;i++)
		for(int j = 0;j<N;j++)
			conf[i][j] = 3;
}

void dfs(int i,int j){
	conf[i][j]+=1;
	if(conf[i][j]>=3)return;
	dfs(i,j+1);
	dfs(i+1,j);
	dfs(i-1,j);
	dfs(i,j-1);
}//标准的暴力深搜做法

int main(){
	ios_base::sync_with_stdio(false); 
	cin.tie(0);
	cout.tie(0);
	ini();
	int n,m;
	cin >> n >> m;
	char c;
	for(int i = 1;i<=n;i++){
		for(int j = 1;j<=m;j++){
			cin >> c;
			conf[i][j] = (c=='X')+1;
		}
	}
	int c1,c2,e1,e2;
	cin >> c1 >> c2 >> e1 >> e2;
 	conf[c1][c2] = 1;
	dfs(c1,c2);
	if(conf[e1][e2]>=3)
		puts("YES");
	else
		puts("NO"); 
 	return 0;
}
4.2 Dalao代码 #002
// From cnnfls_csy
// Rating 2937
#include <iostream>
#include <algorithm>
#include<cmath>
#include<cstring>
#include<cstdio>
#include<cstdlib>
#include<vector>
#include<iomanip>
#include<queue>
#define sqr(x) (x)*(x)
using namespace std;
int dx[5]={0,-1,1,0,0},dy[5]={0,0,0,-1,1};
int n,m,i,j,ex,ey,sx,sy,x,y;
char mp[505][505];
queue<int> qx,qy;
int main()
{
	cin>>n>>m;
	for (i=1;i<=n;i++)
	{
		for (j=1;j<=m;j++)
		{
			cin>>mp[i][j];
		}
	}
	cin>>sx>>sy>>ex>>ey;
	qx.push(sx);
	qy.push(sy);
	while (!qx.empty())
	{
		x=qx.front();
		y=qy.front();
		qx.pop();
		qy.pop();
		for (i=1;i<=4;i++)
		{
			if (mp[x+dx[i]][y+dy[i]]=='.')
			{
				mp[x+dx[i]][y+dy[i]]='X';
				qx.push(x+dx[i]);
				qy.push(y+dy[i]);
			}
			else if (mp[x+dx[i]][y+dy[i]]=='X'&&x+dx[i]==ex&&y+dy[i]==ey)
			{
				cout<<"YES";
				return 0;
			}
		}
	}//广搜
	cout<<"NO";
	return 0;
}

4.3 蒟蒻代码
#include <bits/stdc++.h>
#define rep(i, a, b) for (register int (i) = (a); (i) <= (b); ++(i))
using namespace std;

struct node {
    int x, y;
} a, b;

bool flag;
queue <node> ppp;
int bj[507][507];
char mp[507][507];
int mov[4][2] = {1, 0, 0, -1, 0, 1, -1, 0};
int n, m, sx, sy, ex, ey;

int main() {
    scanf("%d%d", &n ,&m);
    getchar();
	rep(i, 0, n - 1) {
        rep(j, 0, m - 1)
            scanf("%c", &mp[i][j]);
        getchar();
    }
    scanf("%d%d%d%d", &sx, &sy, &ex, &ey);
    a.x = sx - 1;
    a.y = sy -1;
    --ex;
    --ey;
    ppp.push(a);
    while (!ppp.empty()) {
        a = ppp.front();
        ppp.pop();
        if ((mp[a.x - 1][a.y] == 'X' && a.x - 1 == ex && a.y == ey)
	        	|| (mp[a.x][a.y - 1] == 'X' && a.x == ex && a.y - 1 == ey)
	        	|| (mp[a.x + 1][a.y] == 'X' && a.x + 1 == ex && a.y == ey)
	        	|| (mp[a.x][a.y + 1] == 'X' && a.x == ex && a.y + 1 == ey)) {
            flag = true;
            break;
        }
		rep(i, 0, 3) {
            b.x = a.x + mov[i][0];
            b.y = a.y + mov[i][1];
            if (b.x < 0 || b.y < 0 || b.x >= n || b.y >= m
            		|| bj[b.x][b.y] || mp[b.x][b.y] == 'X')
                continue;
            ppp.push(b);
            mp[b.x][b.y] = 'X';
            bj[b.x][b.y] = 1;
        }
    }
    puts(flag ? "YES" : "NO");
    return 0;
}//本蒟蒻的奇妙码风
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值