CF540C Ice Cave 解题报告

CF540C Ice Cave 解题报告

1 题目链接

http://codeforces.com/contest/540/problem/C

2 题目整理

2.1 题目 : 冰洞
2.2 题目描述

你玩电脑游戏。你的角色站在一个多层次的冰洞的某个层次上。为了继续前进,你需要下降一层,唯一的方法就是从冰上掉下来。

你所在的洞穴层级是一个n行m列的矩形方格。每个细胞要么由完整的冰组成,要么由破裂的冰组成。您可以从每个单元格移动到与您的单元格相邻的单元格(由于游戏引擎的某些限制,您不能在同一个地方进行跳跃,即从一个单元格跳到它自己)。如果你移动到破裂的冰块,那么你的角色会从里面掉下来,如果你移动到完整的冰块,那么这个冰块上的冰就会裂开。

让我们从上到下用从1到n的整数对行进行编号,从左到右用从1到m的整数对列进行编号。让我们将第r行和第c列的交叉点上的单元格表示为(r,c)。

你待在(r1, c1)这个冰块上,这个冰块破裂了,因为你刚刚从更高的层次跌落到这里。您需要从牢房(r2, c2)中跌落,因为那里有通往下一层的出口。你能做这个吗?

2.3 输入格式

第一行包含两个整数n和m — 洞穴描述中的行数和列数。

接下来的n行中的每一行都描述了洞穴层的初始状态,每行由m个字符“ . ”(即完整的冰)和“ X ”(破裂的冰)组成。

下一行包含两个整数,r1和c1 —— 你的初始坐标。保证洞穴的描述在单元格(r1,? c1)中包含字符’ X ’ ,即起始单元格上的冰最初是破裂的。

下一行包含两个整数r2和c2 ——你需要穿过的单元格的坐标。最后的单元格可能与开始的单元格重合。

2.4 输出格式

如果可以到达目的地,打印’ YES ‘,否则打印’ NO '。

2.5.1 样例输入1
4 6
X...XX
...XX.
.X..X.
......
1 6
2 2
2.5.2 样例输出1
YES
2.6.1 样例输入2
5 4
.X..
...X
X.X.
....
.XX.
5 3
1 1
2.6.2 样例输出2
NO
2.7.1 样例输入3
4 7
..X.XX.
.XX..X.
X...X..
X......
2 2
1 6
2.7.2 样例输出3
YES
2.8 数据范围

对于 100 % 100\% 100%的数据:
1 ≤ n , m ≤ 500 1 \le n,m \le 500 1n,m500
1 ≤ r 1 ≤ n , 1 ≤ c 1 ≤ m 1 \le r_1 \le n,1 \le c_1 \le m 1r1n,1c1m
1 ≤ r 2 ≤ n , 1 ≤ c 2 ≤ m 1 \le r_2 \le n,1\le c_2 \le m 1r2n,1c2m

3 题意分析

3.1 题目大意

给你一个地图,开始你在(r1,c1)上,不能走到’X’上,且(r2,c2)需走两次,而其他格只能走一次。
能否满足上述要求,且最后停在(r2,c2)上?

3.2 样例分析

如上所述。

解法分析

这道题其实和普通的搜索题有神似,但这道题(r2,c2)需要走两次,那就要处理这个问题。其实,
最一般的做法是暴力广搜,在(r2,c2)上特判一下即可。但我有一个做法:
不难发现,若第一次已经走到了(r2,c2)上的话,只要周围还有一个格子能走,就一定可以成功。
那么,不仿先将周围的一块格子先保护起来,然后再跑一遍广搜,只要走得到(r2,c2),那就可
已第二次走到(r2,c2)。

4 AC代码

ACCode #1
// 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;
}

ACCode #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;
}
ACCode #003
// From Heart_Blue
// Rating 2425
#include <cstdlib>
#include <cctype>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <vector>
#include <string>
#include <iostream>
#include <sstream>
#include <map>
#include <set>
#include <queue>
#include <stack>
#include <fstream>
#include <numeric>
#include <iomanip>
#include <bitset>
#include <list>
#include <stdexcept>
#include <functional>
#include <utility>
#include <ctime>
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
#define MAX(a,b) ((a) > (b) ? (a) : (b))
#define MIN(a,b) ((a) < (b) ? (a) : (b))
#define MEM(a,b) memset((a),(b),sizeof(a))
const LL INF = 1e9 + 7;
const int N = 5e2 + 10;
char chess[N][N];
int dx[] = { 0,0,1,-1 };
int dy[] = { -1,1,0,0 };
int flag[N][N];
int main()
{
	//freopen("input.txt", "r", stdin);
	//freopen("output.txt", "w", stdout);
	int n, m;
	cin >> n >> m;
	MEM(chess, 'X');
	for (int i = 1; i <= n; i++)
	{
		for (int j = 1; j <= m; j++)
		{
			cin >> chess[i][j];
		}
	}
	int sx, sy;
	int ex, ey;
	cin >> sx >> sy >> ex >> ey;
	int cnt = 0;
	for (int i = 0; i < 4; i++)
	{
		int x = ex + dx[i];
		int y = ey + dy[i];
		if (chess[x][y] == '.') cnt++;
	}
	if (sx == ex && sy == ey)
	{
		if (cnt > 0) puts("YES");
		else puts("NO");
		return 0;
	}
	if (abs(sx - ex) + abs(sy - ey) == 1)
	{
		if (chess[ex][ey] == 'X')
		{
			puts("YES");
		}
		else
		{
			if (cnt > 0) puts("YES");
			else puts("NO");
		}
		return 0;
	}
	MEM(flag, 0);
	list<pair<int, int>> lp;
	lp.push_back({ sx,sy });
	flag[sx][sy] = 1;
	while (!lp.empty())
	{
		int x, y;
		tie(x, y) = lp.front();
		lp.pop_front();
		for (int i = 0; i < 4; i++)
		{
			int tx = x + dx[i];
			int ty = y + dy[i];
			if (flag[tx][ty]) continue;
			flag[tx][ty] = 1;
			if (chess[tx][ty] == 'X') continue;
			lp.push_back({ tx,ty });
		}
	}
	if (flag[ex][ey])
	{
		if (chess[ex][ey] == 'X') puts("YES");
		else if (cnt > 1) puts("YES");
		else puts("NO");
	}
	else puts("NO");
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值