POJ-2157(floodfill + BFS)

题目:http://poj.org/problem?id=2157

一开始想的是BFS,然后卡在怎样怎样记录状态,看了discuss中“在无路可走时才试图去打开能打开的门。。。然后继续行走,此就是广搜策略”才恍然大悟,看来自己对搜索的理解还是太狭隘了……


#include <cstdio>
#include <cstring>

const int dir[4][2] = {
	{1, 0}, {-1, 0}, {0, 1}, {0, -1}
};
int R, C;
char map[22][22];
int sr, sc, needKeyCnt[5];

inline bool isWall(char c){ return c == 'X'; }
inline bool isGate(char c){ return c >= 'A' && c <= 'E'; }
inline bool isKey(char c){ return c >= 'a' && c <= 'e'; }
inline bool isOutOfBound(int r, int c){ return r < 0 || r >= R || c < 0 || c >= C; }

bool hasNeighbourVisited(int r, int c)
{
	for(int i = 0; i < 4; ++i){
		int nr = r + dir[i][0], nc = c + dir[i][1];
		if(!isOutOfBound(nr, nc) && map[nr][nc] == '@') return true;
	}
	return false;
}
bool input()
{
	if(scanf("%d%d", &R, &C), !R) return false;
	while(getchar() != '\n') ;

	memset(needKeyCnt, 0, sizeof(needKeyCnt));
	for(int i = 0; i < R; ++i){
		char* p = strchr(gets(map[i]), 'S');
		if(p) sr = i, sc = p - map[i];
		for(p = map[i]; *p; ++p)
			if(isKey(*p)) ++needKeyCnt[*p - 'a'];
	}
	return true;
}
bool floodfill(int r, int c)
{
	if(map[r][c] == 'G') return true;
	if(isKey(map[r][c])) --needKeyCnt[map[r][c] - 'a'];//we get a new key
	map[r][c] = '@';//mark as visited

	for(int i = 0; i < 4; ++i){
		int nr = r + dir[i][0], nc = c + dir[i][1];
		if(isOutOfBound(nr, nc) || isWall(map[nr][nc]) || isGate(map[nr][nc])) continue;
		if(map[nr][nc] != '@' && floodfill(nr, nc)) return true;
	}
	return false;
}
bool hasPath()
{
	if(floodfill(sr, sc)) return true;
	for(int i = 0; i < R; ++i)
		for(int j = 0; j < C; ++j)
			if(isGate(map[i][j]) && needKeyCnt[map[i][j]-'A'] <= 0 &&
			   hasNeighbourVisited(i, j) && floodfill(i, j)) return true;
	return false;
}

int main()
{
	while(input()) puts(hasPath() ? "YES" : "NO");
	return 0;
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值