HDU 5025 Saving Tang Monk(bfs+状压) 【openjudge】

Saving Tang Monk

问题分析

本题就是属于拿钥匙去开门的 b f s 类题目。
题意:孙悟空必须拿到 n 个钥匙才能救出唐僧,但是期间如果遇到蛇怪需要多花一分钟去打败她们,并且在拿到第 i 个钥匙之前必须先拿到第 i 1 个钥匙,问最少的花费时间。

这题就麻烦在三个地方,
一、同种钥匙可能有多个,拿完钥匙的地方仍然可以走,所以需要加一维钥匙的状态来判重。
二、因为打败蛇怪需要多花费时间,所以肯定要优先走不经过蛇怪的最短路,优先队列解决。
三、打过蛇怪的地方仍然可以走动,所以需要判断蛇洞里的蛇怪 d e a d 没有,所以需要节点加一个打蛇怪的状态 ( s n a k e ) 。就比如用 0 , 1 , 2 , 3 , 4... 给蛇编号的,判断 i 号蛇怪是否死亡就用当前的状态 s n a k e & ( 1 << i ) ,如果结果等于0则说明i蛇怪还没有 d e a d ,否则就是 d e a d

#include <bits/stdc++.h>

struct node {
    int x, y, step, snake, key;

    bool operator<(const node &u) const {
        return step > u.step;
    }
};

const int dir[4][2] = {0, 1, 1, 0, 0, -1, -1, 0};
bool vis[111][111][11];
char a[111][111];
int n, m, snakeLoc[111][111];

int rec(int stx, int sty, int desx, int desy) {
    std::priority_queue<node> pq;
    node cur, nxt;
    cur.x = stx, cur.y = sty, cur.step = cur.key = cur.snake = 0;
    pq.push(cur);
    while (!pq.empty()) {
        cur = pq.top();
        pq.pop();
        if (cur.x == desx && cur.y == desy && cur.key == m)
            return cur.step;
        for (int i = 0; i < 4; ++i) {
            int tx = cur.x + dir[i][0];
            int ty = cur.y + dir[i][1];
            int key = cur.key, step = cur.step + 1, snake = cur.snake;
            if (a[tx][ty] == cur.key + '1')
                key++;
            if (tx < 0 || tx >= n || ty < 0 || ty >= n || vis[tx][ty][key] || a[tx][ty] == '#')
                continue;
            if (a[tx][ty] == 'S' && ((snake & (1 << snakeLoc[tx][ty])) == 0)) //if it is a alive snake
                step++, snake |= (1 << snakeLoc[tx][ty]);
            vis[tx][ty][key] = 1;
            nxt = {tx, ty, step, snake, key};
            pq.push(nxt);
        }
    }
    return -1;
}

int main() {
    while (~scanf("%d%d", &n, &m) && (n + m)) {
        int stx, sty, desx, desy, cnt = 0;
        memset(vis, 0, sizeof vis);
        memset(snakeLoc, 0, sizeof(snakeLoc));
        for (int i = 0; i < n; ++i)
            for (int j = 0; j < n; ++j) {
                scanf(" %c", &a[i][j]);
                if (a[i][j] == 'K') stx = i, sty = j;
                if (a[i][j] == 'T') desx = i, desy = j;
                if (a[i][j] == 'S') snakeLoc[i][j] = cnt++;
            }
        int ans = rec(stx, sty, desx, desy);
        if (ans == -1) puts("impossible");
        else printf("%d\n", ans);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/Eternally831143/article/details/81370138
今日推荐