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;
}//本蒟蒻的奇妙码风