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;
}
咦?当时有个点没过,有好心人帮我看看哪错了吧……