状压,BFS
https://www.luogu.com.cn/problem/P4011
有一个 \(n*m\) 的迷宫,每个格子到相邻格子可能有墙,也可能有门,钥匙会散落在迷宫中的一些格子内,问从 \((1,1)\) 走到 \((n,m)\) 的最短路径长度
Tutorial这个网络流24题是谁搞出来的东西,两题都不用网络流写,甚至网络流写法看上去有些蠢。
普通bfs,没啥好说的。
#include <bits/stdc++.h>
typedef long long ll;
#define endl '\n'
#define P pair<int, int>
#define eps 1e-8
#define IOS \
ios::sync_with_stdio(0); \
cin.tie(0); \
cout.tie(0);
using namespace std;
const int N = 15 + 5;
const int mod = 1e9 + 7;
const int INF = 0x3f3f3f3f;
typedef long long ll;
struct node {
int x, y, step, st;
node(int _x, int _y, int _step, int _st) {
x = _x, y = _y, step = _step, st = _st;
}
};
int dx[] = {0, 1, 0, -1};
int dy[] = {1, 0, -1, 0};
int n, m, p;
bool vis[N][N][1 << 14 + 6];
int mp[N][N][N][N];
vector<int> key[N][N];
inline bool check(int x, int y, int s) {
return 0 < x && x <= n && 0 < y && y <= m;
}
int solve() {
queue<node> q;
int sst = 0;
for (int i : key[1][1])
sst |= (1 << (i - 1));
q.emplace(1, 1, sst, 0);
vis[1][1][sst] = 1;
while (q.size()) {
node o = q.front();
q.pop();
if (o.x == n && o.y == m)
return o.step;
// cout<<"->"<<o.x<<" "<<o.y<<endl;
for (int dir = 0; dir < 4; dir++) {
int dx = o.x + ::dx[dir], dy = o.y + ::dy[dir];
if (!check(dx, dy, o.st))
continue;
int walk = mp[o.x][o.y][dx][dy];
if (walk && !((1 << (walk - 1)) & o.st))
continue;
int ds = o.st;
for (auto i : key[dx][dy]) {
ds |= (1 << (i - 1));
}
if (vis[dx][dy][ds])
continue;
vis[dx][dy][ds] = 1;
q.emplace(dx, dy, o.step + 1, ds);
}
}
return -1;
}
int main() {
cin >> n >> m >> p;
// cout << "----\n";
cin >> p;
for (int i = 0, x1, y1, x2, y2, g; i < p; i++) {
cin >> x1 >> y1 >> x2 >> y2 >> g;
mp[x1][y1][x2][y2] = mp[x2][y2][x1][y1] = g;
if (!g)
mp[x1][y1][x2][y2] = mp[x2][y2][x1][y1] = -1;
}
int s;
cin >> s;
for (int i = 0, x, y, g; i < s; i++) {
cin >> x >> y >> g;
key[x][y].push_back(g);
}
int ans = solve();
cout << ans << endl;
}