网络流24题 之十四 孤岛营救问题 分层图

题目大意:一张网格图,上面有一些点可能有某种钥匙。节点和节点之间可能有门。有些门需要特定的钥匙就可以通过,有些无论如何都过不去。求从(1,1)开始到(m,n)的最短时间。


思路:分层图+状态压缩。f[i][j][k],其中i和j描述的是当前所在的位置,k是压缩了的当前有哪些钥匙(由于钥匙的数量<=10,所以所有的状态1<<10的空间内就可以搞定)。然后向四个方向更新的时候判断是否能经过门。


CODE:


#include <queue>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define MAX 20
#define INF 0x3f3f3f3f
using namespace std;
const int dx[] = {0,1,-1,0,0};
const int dy[] = {0,0,0,1,-1};

struct Complex{
	int x,y,status;

	Complex(int _,int __,int ___):x(_),y(__),status(___) {}
	Complex() {}
};

int m,n,p,doors,keys;
int f[MAX][MAX][1 << 11];
bool v[MAX][MAX][1 << 11];
int map[MAX][MAX][MAX][MAX];
int key[MAX][MAX];

void SPFA();
inline bool Accelerator(int x1,int y1,int x2,int y2,int status);

int main()
{
	cin >> m >> n >> p >> doors;
	memset(map,-1,sizeof(map));
	for(int a,b,c,d,x,i = 1;i <= doors; ++i) {
		scanf("%d%d%d%d%d",&a,&b,&c,&d,&x);
		map[a][b][c][d] = map[c][d][a][b] = x;
	}
	cin >> keys;
	for(int x,y,z,i = 1;i <= keys; ++i) {
		scanf("%d%d%d",&x,&y,&z);
		key[x][y] |= 1 << z;
	}
	SPFA();
	int ans = INF;
	for(int i = 0;i < (1 << 11); ++i)
		ans = min(ans,f[m][n][i]);
	if(ans == INF)	ans = -1;
	cout << ans << endl;
	return 0;
}

void SPFA()
{
	memset(f,0x3f,sizeof(f));
	f[1][1][0] = 0;
	static queue<Complex> q;
	while(!q.empty())	q.pop();
	q.push(Complex(1,1,0));
	while(!q.empty()) {
		Complex now = q.front(); q.pop();
		v[now.x][now.y][now.status] = false;
		int _status = now.status;
		if(key[now.x][now.y])	_status |= key[now.x][now.y];
		for(int i = 1;i <= 4; ++i) {
			int fx = now.x + dx[i];
			int fy = now.y + dy[i];
			if(!fx || !fy || fx > m || fy > n)	continue;
			if(Accelerator(now.x,now.y,fx,fy,_status))
				if(f[fx][fy][_status] > f[now.x][now.y][now.status] + 1) {
					f[fx][fy][_status] = f[now.x][now.y][now.status] + 1;
					if(!v[fx][fy][_status])
						v[fx][fy][_status] = true,q.push(Complex(fx,fy,_status));
				}
		}
	}
}

inline bool Accelerator(int x1,int y1,int x2,int y2,int status)
{
	int need_key = map[x1][y1][x2][y2];
	if(!need_key)	return false;
	if(need_key == -1)	return true;
	return (status >> need_key)&1;
}


你可能感兴趣的:(动态规划,SPFA,状态压缩,分层图,网络流24题)