FZUOJ2196 Escape(bfs)

Accept: 122    Submit: 665
Time Limit: 1000 mSec    Memory Limit : 32768 KB

 Problem Description

小明进入地下迷宫寻找宝藏,找到宝藏后却发生地震,迷宫各处产生岩浆,小明急忙向出口处逃跑。如果丢下宝藏,小明就能迅速离开迷宫,但小明并不想轻易放弃自己的辛苦所得。所以他急忙联系当程序员的朋友你(当然是用手机联系),并告诉你他所面临的情况,希望你能告诉他是否能成功带着宝藏逃脱。

 Input

有多组测试数据。

每组测试数据第一行是一个整数T,代表接下去的例子数。(0<=T<=10)

接下来是T组例子。

每组例子第一行是两个整数N和M。代表迷宫的大小有N行M列(0<=N,M<=1000)。

接下来是一个N*M的迷宫描述。

S代表小明的所在地。

E代表出口,出口只有一个。

.代表可以行走的地方。

!代表岩浆的产生地。(这样的地方会有多个,其个数小于等于10000)

#代表迷宫中的墙,其不仅能阻挡小明前进也能阻挡岩浆的蔓延。

小明携带者宝藏每秒只能向周围移动一格,小明不能碰触到岩浆(小明不能和岩浆处在同一格)。

岩浆每秒会向四周不是墙的地方蔓延一格。

小明先移动完成后,岩浆才会蔓延到对应的格子里。

小明能移动到出口,则小明顺利逃脱。

 Output

每组测试数据输出只有一行“Yes”或者“No”。 “Yes”代表小明可以成功逃脱。否则输出“No”。

 Sample Input

35 5....!S....#....!#...#E...2 2S.!E2 2SE!.

 Sample Output

YesNoYes



我这种只会做bfs模版题的渣 这题都不敢碰。。


泽神1A 钱神fb 轩神也过了。。


自己的学习方法还是存在问题 看题解太多了 自己思考太少了


两次bfs 第一次计算出岩浆到达每个点的时间 第二次判断小明是否可以逃脱


AC代码:


#include "iostream"
#include "cstdio"
#include "cstring"
#include "algorithm"
#include "queue"
using namespace std;
const int maxn = 1005;
int dx[4] = {1, 0, -1, 0}, dy[4] = {0, 1, 0, -1};
char map[maxn][maxn];
int n, m, tt[maxn][maxn];
bool vis[maxn][maxn];
struct node
{
	/* data */
	int x, y, t;
};
bool judge1(int x, int y)
{
	if(x >= 0 && x < n && y >= 0 && y < m && tt[x][y] == -1 && map[x][y] != '#')
		return true;
	return false;
}
bool judge2(int x, int y)
{
	if(x >= 0 && x < n && y >= 0 && y < m && !vis[x][y] && map[x][y] != '#')
		return true;
	return false;
}
void bfs1()
{
	queue<node> q;
	node f, r;
	memset(tt, -1, sizeof(tt));
	for(int i = 0; i < n; ++i)
		for(int j = 0; j < m; ++j)
			if(map[i][j] == '!') {
				f.x = i;
				f.y = j;
				f.t = 0;
				tt[i][j] = 0;
				q.push(f);
			}
	int x, y;
	while(!q.empty()) {
		f = q.front();
		q.pop();
		for(int i = 0; i < 4; ++i) {
			x = f.x + dx[i], y = f.y + dy[i];
			if(judge1(x, y)) {
				tt[x][y] = f.t + 1;
				r.x = x, r.y = y, r.t = tt[x][y];
				q.push(r);
			}
		}
	}
}
bool bfs2()
{
	queue<node> q;
	node f, r;
	memset(vis, false, sizeof(vis));
	for(int i = 0; i < n; ++i)
		for(int j = 0; j < m; ++j)
			if(map[i][j] == 'S') {
				f.x = i;
				f.y = j;
				f.t = 0;
				vis[i][j] = true;
			}
	q.push(f);
	int x, y;
	while(!q.empty()) {
		f = q.front();
		q.pop();
		for(int i = 0; i < 4; ++i) {
			x = f.x + dx[i], y = f.y + dy[i];
			if(judge2(x, y) && tt[x][y] >= f.t + 1) {
				vis[x][y] = true;
				if(map[x][y] == 'E') return true;
				else if(tt[x][y] != f.t + 1) {
					r.x = x, r.y = y, r.t = f.t + 1;
					q.push(r);
				}
			}
		}
	}
	return false;
}
int main(int argc, char const *argv[])
{
	int t;
	scanf("%d", &t);
	while(t--) {
		scanf("%d%d", &n, &m);
		for(int i = 0; i < n; ++i)
			scanf("%s", map[i]);
		bfs1();
		if(bfs2()) printf("Yes\n");
		else printf("No\n");
	}
	return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值