现在的位置: 首页 > 综合 > 正文

poj2157

2013年07月16日 ⁄ 综合 ⁄ 共 826字 ⁄ 字号 评论关闭

题目:http://poj.org/problem?id=2157
题意比较简单,就是走迷宫,然后有些地方是需要钥匙才能打开,并且是需要集齐这扇门的所有钥匙才能打开的
思路就是,首先广搜一下,并且将所有可以收集的钥匙都收集起来,看可不可以达到目的地,如果可以,那就不需要再走下去了,如果不可以,这时就把能打开的门全部打开,然后再重复上述步骤,一直到到达目的地,或者还有门打不开并且到不了目的地,结束算法
代码:

#include<cstdio>
#include<cstring>
#define MAXN 21
#include<queue>
using namespace std;
 
char maps[MAXN][MAXN];
int visited[MAXN][MAXN];
int dir[4][2] = {-1, 0, 0, -1, 1, 0, 0, 1};
int N, M, sx, sy, ex, ey;
int key_num[5];
int count[5];
struct Point{
    int px, py;
};
struct Door{
    int x, y;
};
Door doors[5];
 
bool BFS() {
    Point start;
    start.px = sx;
    start.py = sy;
    memset(visited, 0, sizeof(visited));
    queue<Point>Q;
    Q.push(start);
    while(!Q.empty()) {
        Point hd = Q.front();
        Q.pop();
        if(maps[hd.px][hd.py] == 'G') {
            return true;
        }
        for(int i = 0; i < 4; ++ i) {
            int x = hd.px + dir[i][0];
            int y = hd.py + dir[i][1];
            if(x < 0 || x >= M || y < 0 || y >= N) {
                continue;
            }
            if(visited[x][y] || maps[x][y] == 'X' || maps[x][y] >= 'A' && maps[x][y] <= 'E') {
                continue;
            }
            visited[x][y] = 1;
            if(maps[x][y] >= 'a' && maps[x][y] <= 'e') {
                count[maps[x][y] - 'a']++;
                maps[x][y] = '.';
            }
            Point t;
            t.px = x;
            t.py = y;
            Q.push(t);
        }
    }
    return false;
}
 
int main() {
    freopen("poj2157.txt", "r", stdin);
    while(scanf("%d%d", &M, &N), M, N) {
        memset(key_num, 0, sizeof(key_num));
        memset(count, -1, sizeof(count));
        for(int i = 0; i < M; ++ i) {
            scanf("%s", maps[i]);
            for(int j = 0; j < N; ++ j) {
                if(maps[i][j] == 'S') {
                    sx = i;
                    sy = j;
                }
                if(maps[i][j] == 'G') {
                    ex = i;
                    ey = j;
                }
                if(maps[i][j] >= 'a' && maps[i][j] <= 'e') {//记录每种钥匙的总数,在判断是否可以打开门的时候用
                    key_num[maps[i][j] - 'a']++ ;
                }
                if(maps[i][j] >= 'A' && maps[i][j] <= 'E') {//记录所有门的位置,这里应该是每种门只有一扇的,discuss里面说的不能信
                    doors[maps[i][j] - 'A'].x = i;
                    doors[maps[i][j] - 'A'].y = j;
                }
            }
        }
        if(BFS()) {//不需要打开门,就可以直接到达目的地
            printf("YES\n");
        } else {
            while(1) {
                bool door_open = false;//标记是否有门可以被打开
                for(int i = 0; i <5; ++ i) {
                    if(count[i] == -1) {//不存在这扇门的钥匙
                        continue;
                    } else if(count[i] == key_num[i] - 1) {//有这扇门的钥匙,并且找到的钥匙的个数刚好等于所需的钥匙的个数,这里减一是因为初始化时memset是把count置成-1的
                        count[i] = -1;//可以打开这扇门,所有找到的这扇门的钥匙都被用掉了
                        maps[doors[i].x][doors[i].y] = '.';//修改地图
                        door_open = true;//有门可以被打开
                    }
                }
                if(door_open) {
                    if(BFS()) {//打开某些门后可以到达目的地
                        printf("YES\n");
                        break;
                    }
                } else {//没有门可以打开
                    printf("NO\n");
                    break;
                }
            }
        }
    }
}

抱歉!评论已关闭.