跳刀抓人(分层图BFS)

题意

给定一个\(n \times m\)的网格图,其中一些格子是平地,可以走;一些格子是障碍物,不能走。给定起点\(S\)和终点\(T\),现在要从\(S\)走到\(T\)
现在有三种行动方式,但是无论是哪种行动方式,都不能超出地图的范围:

  • 移动到上下左右某一个相邻的平地格子,花费时间\(1s\)
  • 使用道具,可以移动到距离当前点切比雪夫距离不超过\(3\)的平地格子(切比雪夫距离:\(max(|x1 - x2|, |y1 - y2|)\)),花费时间\(1s\)。但是这个道具有冷却时间\(7s\)
  • 原地不动
    道具第一次使用可以不用冷却。问从\(S\)\(T\)的最小花费时间。

思路

\(2 \leq n, m \leq 100\)

思路

分层图最短路板子题。将原图复制\(7\)份,这\(8\)个图从\(0\)\(7\)标号,表示当前层道具的冷却时间。

在BFS的过程中,将位置和冷却时间传进队列。同时距离数组也是两维的\(\{p, t\}\),表示到当前位置\(p\),道具冷却时间为\(t\)需要的最短时间。

代码

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>

using namespace std;

typedef pair<int, int> pii;
typedef pair<pii, int> ppi;

const int N = 110, M = 10;

int n, m;
int sx, sy, ex, ey;
char s[N][N];
int d[N][N][M];

int dx[5] = {-1, 1, 0, 0, 0};
int dy[5] = {0, 0, -1, 1, 0};

int main()
{
    scanf("%d%d", &n, &m);
    for(int i = 1; i <= n; i ++) scanf("%s", s[i] + 1);
    for(int i = 1; i <= n; i ++) {
        for(int j = 1; j <= m; j ++) {
            if(s[i][j] == 'A') {
                sx = i;
                sy = j;
            }
            if(s[i][j] == 'B') {
                ex = i;
                ey = j;
            }
        }
    }
    memset(d, 0x3f, sizeof d);
    d[sx][sy][0] = 0;
    queue<ppi> que;
    que.push({{sx, sy}, 0});
    while(que.size()) {
        auto t = que.front();
        que.pop();
        int tx = t.first.first, ty = t.first.second;
        int time = t.second;
        for(int i = 0; i < 5; i ++) {
            int x = tx + dx[i], y = ty + dy[i];
            if(x < 1 || x > n || y < 1 || y > m) continue;
            if(s[x][y] == '#') continue;
            if(d[x][y][max(0, time - 1)] > d[tx][ty][time] + 1) {
                d[x][y][max(0, time - 1)] = d[tx][ty][time] + 1;
                que.push({{x, y}, max(0, time - 1)});
            }
        }
        if(!time) {
            for(int i = tx - 3; i <= tx + 3; i ++) {
                for(int j = ty - 3; j <= ty + 3; j ++) {
                    if(i < 1 || i > n || j < 1 || j > m) continue;
                    if(s[i][j] == '#') continue;
                    if(max(abs(i - tx), abs(j - ty)) > 3) continue;
                    if(d[i][j][7] > d[tx][ty][time] + 1) {
                        d[i][j][7] = d[tx][ty][time] + 1;
                        que.push({{i, j}, 7});
                    }
                }
            }
        }
    }
    int ans = 0x3f3f3f3f;
    for(int i = 0; i <= 7; i ++) ans = min(ans, d[ex][ey][i]);
    if(ans == 0x3f3f3f3f) ans = -1;
    printf("%d\n", ans);
    return 0;
}
posted @ 2022-03-28 10:39  pbc的成长之路  阅读(79)  评论(0编辑  收藏  举报