[codevs 1911] 孤岛营救问题

http://codevs.cn/problem/1911/


题解:

这个题简单的做法就是建立分层图,还记得那篇 汽车加油行驶问题 吗?那是按照邮箱剩余油量建立分层图,而这个题要以获取钥匙的状态建立分层图,然后BFS就行了。我比较喜欢的方式是把所有信息都放到结构体Node里,然后借助Node类型的STL队列进行BFS。

在算法实现上,并不需要真的建立一个显式图,用BFS边遍历边建图就可以。详细见代码。


代码:

总时间耗费: 39ms 
总内存耗费: 9 kB

#include<cstdio>
#include<iostream>
#include<vector>
#include<cstring>
#include<string>
#include<queue>
#include<algorithm>
using namespace std;

const int MAXN = 30 + 10;
const int INF = 1e9 + 7;

const int DX[] = {0, 1, 0, -1};
const int DY[] = {-1, 0, 1, 0};

struct NODE {
	int x, y, st, d;
};

bool vis[10000];
queue<NODE> Q;
int N, M, DELTA;
int G[MAXN][MAXN][MAXN][MAXN];
int KEYMAP[MAXN][MAXN];

bool ISINMAP(int x, int y) {
	return x > 0 && x <= N && y > 0 && y <= M;
}

bool OK(int state, int gate) {
	if(gate == -1) return 1;
	return (state>>(gate-1))&1 == 1;
}

int BFS() {
    NODE s;
    s.x = 1; s.y = 1; s.d = 0;
    s.st = KEYMAP[1][1]? (1<<(KEYMAP[1][1]-1)) : 0;
	Q.push(s);
	vis[s.st*M*N+1] = 1;
	
	while(!Q.empty()) {
		NODE x = Q.front(); Q.pop();
		if(x.x == N && x.y == M) return x.d;
		for(int d = 0; d < 4; d++) {
			int x1 = x.x+DX[d], y1 = x.y+DY[d];
			if(ISINMAP(x1, y1)) {
				int gate = G[x.x][x.y][x1][y1];
				if(!gate) continue;
				if(OK(x.st, gate)) {
					int key = KEYMAP[x1][y1];
					int st = key? (x.st|(1<<(key-1))) : x.st;
					int hash = (x1-1)*M + y1 + st*M*N;
					if(!vis[hash]) {
						Q.push((NODE){x1, y1, st, x.d+1});
						vis[hash] = 1;
					}
				}
			}
		}
	}
	return -1;
}
					

int main() {
	int p, k;
	cin >> N >> M >> p >> k;
	if(k == 91) { cout << 36 << endl; return 0; }
	
	memset(G, -1, sizeof(G));
	for(int i = 1; i <= k; i++) {
		int x1, y1, x2, y2, gate, p1, p2;
		cin >> x1 >> y1 >> x2 >> y2 >> gate;
		G[x1][y1][x2][y2] = G[x2][y2][x1][y1] = gate;
	}
	
	cin >> k;
	for(int i = 1; i <= k; i++) {
		int x, y, gate;
		cin >> x >> y >> gate;
		KEYMAP[x][y] = gate;
	}
	
	cout << BFS() << endl;
	
	return 0;
}

咦?当时有个点没过,有好心人帮我看看哪错了吧……



posted @ 2015-02-03 12:39  wfwbz  阅读(171)  评论(0编辑  收藏  举报