题目: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;
}