【网络流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;
}
posted @ 2018-01-06 10:29  租酥雨  阅读(292)  评论(1编辑  收藏  举报