「网络流 24 题」孤岛营救问题
设状态$(x,y,h)$为 到点$(x,y)$当前钥匙集合为$h$的最短用时, $bfs$求出最短路即可.
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <set>
#include <map>
#include <queue>
#define REP(i,a,n) for(int i=a;i<=n;++i)
#define PER(i,a,n) for(int i=n;i>=a;--i)
using namespace std;
typedef tuple<int,int,int,int> t4;
typedef tuple<int,int,int> t3;
const int dx[]={0,0,-1,1};
const int dy[]={-1,1,0,0};
int n, m, p, k, s;
map<t4,int> f;
set<t3> vis;
map<t3,int> dis;
int a[20][20];
queue<t3> q;
int main() {
scanf("%d%d%d%d", &n, &m, &p, &k);
REP(i,1,k) {
int x1,y1,x2,y2,g;
scanf("%d%d%d%d%d", &x1,&y1,&x2,&y2,&g);
f[t4(x2,y2,x1,y1)] = f[t4(x1,y1,x2,y2)] = g?1<<g-1:1<<p;
}
scanf("%d", &s);
REP(i,1,s) {
int x,y,q;
scanf("%d%d%d",&x,&y,&q);
a[x][y] |= 1<<q-1;
}
q.push(t3(1,1,a[1][1]));
dis[q.front()] = 0;
vis.insert(q.front());
int ans = 1e9;
while (q.size()) {
t3 u = q.front(); q.pop();
int x,y,h;
tie(x,y,h) = u;
if (x==n&&y==m) ans = min(ans, dis[u]);
REP(i,0,3) {
int xx=x+dx[i],yy=y+dy[i];
if (1<=xx&&xx<=n&&1<=yy&&yy<=m) {
t3 v(xx,yy,h|a[xx][yy]);
if (vis.count(v)) continue;
int t = f[t4(x,y,xx,yy)];
if ((h|t)==h) {
dis[v] = dis[u]+1;
vis.insert(v);
q.push(v);
}
}
}
}
printf("%d\n",ans==1e9?-1:ans);
}

浙公网安备 33010602011771号