AcWing
  • 首页
  • 活动
  • 题库
  • 竞赛
  • 应用
  • 更多
    • 题解
    • 分享
    • 商店
    • 问答
    • 吐槽
  • App
  • 登录/注册

走迷宫升级版

作者: 作者的头像   若雨 ,  2023-05-24 09:09:47 ,  所有人可见 ,  阅读 53


3


1

单点时限: 2.0 sec
内存限制: 256 MB
一天,sunny 不小心进入了一个迷宫,不仅很难寻找出路,而且有的地方还有怪物,但是 sunny 有足够的能力杀死怪物,但是需要一定的时间,但是 sunny 想早一点走出迷宫,所以请你帮助他计算出最少的时间走出迷宫,输出这个最少时间。

我们规定每走一格需要时间单位 1, 杀死怪物也需要时间 1, 如果不能走到出口,则输出 impossible. 每次走只能是上下左右 4 个方向。

输入格式
每次首先 2 个数 n,m (0<n,m≤200),代表迷宫的高和宽,然后 n 行,每行 m 个字符。

S 代码你现在所在的位置。
T 代表迷宫的出口。

代表墙,你是不能走的。

X 代表怪物。
. 代表路,可以走。
处理到文件结束。

输出格式
输出最少的时间走出迷宫。不能走出输出 impossible。

样例
输入样例:

4 4
S.X.
#..#
..#.
X..T
4 4
S.X.
#..#
..#.
X.#T

输出样例:

6
impossible

代码

// 稠密图使用邻接矩阵,稀疏图使用邻接表;
// 相比权值相等的走迷宫,其各权值不同,本质上是最短路径问题,因此不可使用是否标记来判断是否更新;
// --> dis存储到该节点的最短路径 + 优先队列存储最短距离对应的顶点。
#include <iostream>
#include <stdio.h>
#include <queue>

using namespace std;

int dx[4] = {-1, 0, 1, 0}, dy[4] = {0, 1, 0, -1};     // 上右下左 顺时针四个方向的矩阵偏移

struct node {
    int x,  y, dis;
};

bool operator < (const node & a, const node & b) {
    return a.dis > b.dis;
}

const int N = 210;
char g[N][N];
int n, m;
typedef pair<int, int> PII;
struct node Prev[N][N];

void bfs(PII S, PII T){
    int sx = S.first, sy = S.second, tx = T.first, ty = T.second;

    priority_queue <node> heap;   // 小项堆
    heap.push({sx, sy, 0});
    g[sx][sy] = '#';

    while (!heap.empty())
    {
        node p = heap.top();
        heap.pop();

        if (p.x == tx && p.y == ty){
            cout << p.dis << endl;
            int x = tx, y = ty, d = p.dis;
            while(x != sx || y != sy)
            {
                printf("(%d, %d, %d) <- ", x, y, d);
                node t = Prev[x][y];
                x = t.x, y = t.y, d = t.dis;
            }
            printf("(%d, %d, %d)", sx, sy, 0);
            return;
        }

        for (int i = 0; i < 4; i ++)
        {
            int x = p.x + dx[i], y = p.y + dy[i];
            if (x >= 1 && x <= n && y >= 1 && y <= m && g[x][y] != '#'){
                struct node np {x, y, 0};
                if (g[x][y] == 'X')     np.dis = p.dis + 2;
                // 此时下一顶点为终点时,既不为'.',也不为'X',但距离仍需要加一操作;因此直接使用if-else语句
                else np.dis = p.dis + 1;    // 两种情况:g[x][y] = '.' && g[x][y]为终点
                g[x][y] = '#';
                Prev[x][y] = {p.x, p.y, p.dis};
                heap.push(np);
            }
        }
    }
    cout << "impossible" << endl;
}

int main(){
    cin >> n >> m;
    PII S, T;
    for (int i = 1; i <= n; i ++)
        for (int j = 1; j <= m; j ++){
            cin >> g[i][j];
            if (g[i][j] == 'S')
                S = {i, j};
            if (g[i][j] == 'T')
                T = {i, j};
        }

    bfs(S, T);

    return 0;
}

0 评论

你确定删除吗?

© 2018-2023 AcWing 版权所有  |  京ICP备17053197号-1
用户协议  |  隐私政策  |  常见问题  |  联系我们
AcWing
请输入登录信息
更多登录方式: 微信图标 qq图标 qq图标
请输入绑定的邮箱地址
请输入注册信息