pushbox-quest/optimizer/box-solver.h
2024-01-18 21:49:56 +08:00

73 lines
1.7 KiB
C++

#pragma once
#include <bitset>
#include <queue>
#include <tuple>
#include <cstring>
#include "pushbox.h"
namespace Solve {
thread_local std::bitset<N> mp[N];
thread_local int dis[N][N][N][N];
thread_local std::queue<std::tuple<int, int, int, int>> qu;
inline int bfs(int px, int py, int bx, int by, int tx, int ty) {
std::memset(dis, 127, sizeof(dis));
while (!qu.empty())
qu.pop();
auto expand = [&](int npx, int npy, int nbx, int nby, int d) {
if (npx < 0 || npx >= N)
return;
if (npy < 0 || npy >= N)
return;
if (nbx < 0 || nbx >= N)
return;
if (nby < 0 || nby >= N)
return;
if (mp[npx][npy] == 0)
return;
if (mp[nbx][nby] == 0)
return;
if (npx == nbx && npy == nby)
return;
if (dis[npx][npy][nbx][nby] <= d)
return;
dis[npx][npy][nbx][nby] = d;
qu.emplace(npx, npy, nbx, nby);
};
expand(px, py, bx, by, 0);
while (!qu.empty()) {
auto [npx, npy, nbx, nby] = qu.front();
int d = dis[npx][npy][nbx][nby];
qu.pop();
if (nbx == tx && nby == ty)
return d;
expand(npx + 1, npy, nbx, nby, d + 1);
expand(npx - 1, npy, nbx, nby, d + 1);
expand(npx, npy + 1, nbx, nby, d + 1);
expand(npx, npy - 1, nbx, nby, d + 1);
if (npx + 1 == nbx && npy == nby)
expand(npx + 1, npy, nbx + 1, nby, d + 1);
if (npx - 1 == nbx && npy == nby)
expand(npx - 1, npy, nbx - 1, nby, d + 1);
if (npx == nbx && npy + 1 == nby)
expand(npx, npy + 1, nbx, nby + 1, d + 1);
if (npx == nbx && npy - 1 == nby)
expand(npx, npy - 1, nbx, nby - 1, d + 1);
}
return -1;
}
inline int solve(Maze q) {
for (int i = 0; i < N; ++i)
mp[i] = q.M[i];
return bfs(q.poi[POI_PERSON][0], q.poi[POI_PERSON][1]
, q.poi[POI_BOX][0], q.poi[POI_BOX][1], q.poi[POI_TARGET][0], q.poi[POI_TARGET][1]);
}
}; // namespace Solve