洛谷P9116 题解

题目链接

本题解亮点:

  • 不需要双向广搜。
  • 用普及组方法也能做!

大致思路

  1. bfs 蜜蜂在各个时间点会到达的地方。

  2. 二分答案,枚举小熊等待时长。

具体实现

  1. 读入地图。

  2. 进行第一轮 bfs,求蜜蜂占领各个点需要的时间。我们先将所有蜜蜂的初始位置加入队列,随后再把相邻的单元格入队。

  3. 二分小熊等待时长。每一次二分校验时,需要再跑一次 bfs,而且 bfs 时要设一个时间戳,每到一个点,看他是否超时。对于 \(l\)\(r\),如果 \(mid\) 合法,则将 \(l\) 赋值为 \(mid\),否则将 \(r\) 赋值为 \(mid-1\)

OK,我们可以开始愉快地写代码了(本蒟蒻代码暴丑,大佬勿喷)

#include <bits/stdc++.h>
#define array(x, j) \
    for (int i = 0; i < j; i++) cout << x[i] << " ";
#define ln cout << endl;
#define rpp(i, n) for (int i = 1; i <= n; i++)
#define rep(i, n) for (int i = 0; i < n; i++)
#define bk(i, st, ed) for (int i = st; i >= ed; i--)
#define debug(x) cout << #x << " : " << x << " , on line " << __LINE__ << endl;
#define pb push_back
#define pf push_front
#define iter iterator
#define fi first
#define se second
#define ll long long
using namespace std;
void file(string x) {
    freopen((x + ".in").c_str(), "r", stdin);
    freopen((x + ".out").c_str(), "w", stdout);
}
inline int read() {
    int f = 1, s = 0;
    char c = getchar();
    for (; (c < '0' || c > '9') && c != '-'; c = getchar())
        ;
    if (c == '-') {
        f = -1;
        c = getchar();
    }
    for (; c >= '0' && c <= '9'; c = getchar()) s = (s << 1) + (s << 3) + c - 48;
    return s * f;
}
void FastIO() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    cout.tie(nullptr);
}
template <class Tp>
inline void input(Tp &x) {
    cin >> x;
}
template <class Tp, class... Oth>
inline void input(Tp &x, Oth &... y) {
    input(x), input(y...);
}
template <class Tp>
inline void print(Tp x) {
    cout << x << " ";
};
template <class Tp, class... Oth>
inline void print(Tp x, Oth... y) {
    print(x), print(y...), cout << endl;
}
const int N = 805;
const int dx[] = { -1, 1, 0, 0 };
const int dy[] = { 0, 0, -1, 1 };
char mp[N][N];
bool vis[N][N];
int t[N][N];
int n, s;
struct pos {
    int x, y;
};
struct node {
    int x, y, stp, used;
};
vector<pos> bee;
pos st;
pos ed;
inline bool chk(int x, int y) {
    return x > 0 and x <= n and y > 0 and y <= n and mp[x][y] != 'T' and mp[x][y] != 'D';
}
inline bool chk1(int x, int y, int z) {
    return x > 0 and x <= n and y > 0 and y <= n and !vis[x][y] and t[x][y] > z;
}
void bfs() {
    memset(t, -1, sizeof(t));
    queue<node> q;
    rep(i, bee.size()) {
        q.push({ bee[i].x, bee[i].y, 0 });
        t[bee[i].x][bee[i].y] = 0;
    }
    while (!q.empty()) {
        auto cur = q.front();
        q.pop();
        int x = cur.x;
        int y = cur.y;
        rep(i, 4) {
            int xx = x + dx[i];
            int yy = y + dy[i];
            if (chk(xx, yy) and t[xx][yy] == -1) {
                t[xx][yy] = cur.stp + 1;
                q.push({ xx, yy, cur.stp + 1 });
            }
        }
    }
}
bool calc(int x) {
    memset(vis, 0, sizeof(vis));
    queue<node> q;
    if (t[st.x][st.y] <= x)
        return false;
    q.push({ st.x, st.y, x, 0 });
    vis[st.x][st.y] = 1;
    while (!q.empty()) {
        auto cur = q.front();
        q.pop();
        int x = cur.x;
        int y = cur.y;

        if (cur.x == ed.x and cur.y == ed.y) {
            return true;
        }
        rep(i, 4) {
            int xx = x + dx[i];
            int yy = y + dy[i];
            if (cur.used + 1 == s) {
                if (chk1(xx, yy, cur.stp + 1) or (ed.x == xx and ed.y == yy)) {
                    q.push({ xx, yy, cur.stp + 1, 0 });
                    vis[xx][yy] = 1;
                }
            } else {
                if (chk1(xx, yy, cur.stp) or (ed.x == xx and ed.y == yy)) {
                    q.push({ xx, yy, cur.stp, cur.used + 1 });
                    vis[xx][yy] = 1;
                }
            }
        }
    }
    return false;
}
int main() {
    input(n, s);
    rpp(i, n) {
        scanf("%s", mp[i] + 1);
        rpp(j, n) {
            if (mp[i][j] == 'M') {
                st = { i, j };
            }
            if (mp[i][j] == 'D') {
                ed = { i, j };
            }
            if (mp[i][j] == 'H') {
                bee.pb((pos){ i, j });
            }
        }
    }
    bfs();
    int l = 0, r = n * n;
    while (l < r) {
        int mid = (l + r + 1) >> 1;
        if (calc(mid)) {
            l = mid;
        } else {
            r = mid - 1;
        }
    }
    if (calc(l)) {
        print(l);
    } else {
        print(-1);
    }
    return 0;
}
posted @ 2024-10-03 14:16  XSS_Worm  阅读(12)  评论(0)    收藏  举报