【网络流24题14】孤岛营救问题
题面戳我
题面想放就放啦~
sol
状压当前已获得的钥匙状态,每次与门判一下子集关系,\(BFS\)即可。
code
#include<cstdio>
#include<algorithm>
#include<queue>
using namespace std;
const int N = 20;
int door[N][N][4],key[N][N];
int n,m,p,k,s,dep[N][N][1<<10],ans;
int dx[4]={1,0,-1,0},dy[4]={0,1,0,-1};
struct zt{int x,y,t;};
queue<zt>Q;
int gi()
{
int x=0,w=1;char ch=getchar();
while ((ch<'0'||ch>'9')&&ch!='-') ch=getchar();
if (ch=='-') w=0,ch=getchar();
while (ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
return w?x:-x;
}
int main()
{
n=gi();m=gi();p=gi();
k=gi();
while (k--)
{
int x1=gi(),y1=gi(),x2=gi(),y2=gi(),d1,d2,G=gi();
if (x2==x1+1) d1=0,d2=2;
if (y2==y1+1) d1=1,d2=3;
if (x2==x2-1) d1=2,d2=0;
if (y2==y1-1) d1=3,d2=1;
door[x1][y1][d1]=door[x2][y2][d2]=G?(1<<G-1):(-1);
}
s=gi();
while (s--)
{
int x=gi(),y=gi(),Q=gi();
key[x][y]|=1<<Q-1;
}
Q.push((zt){1,1,0});
dep[1][1][0]=1;
while (!Q.empty())
{
int x=Q.front().x;
int y=Q.front().y;
int t=Q.front().t;Q.pop();
for (int k=0;k<4;k++)
{
int i=x+dx[k],j=y+dy[k];
if (i<1||i>n||j<1||j>m) continue;
int b=t|door[x][y][k],r=t|key[i][j];
if (b^t||dep[i][j][r]) continue;
dep[i][j][r]=dep[x][y][t]+1;Q.push((zt){i,j,r});
}
}
ans=1e9;
for (int i=(1<<p)-1;i;i--)
if (dep[n][m][i])
ans=min(ans,dep[n][m][i]-1);
printf("%d\n",ans==1e9?-1:ans);
return 0;
}