首先关于分层图思想详见2004的这个论文
https://wenku.baidu.com/view/dc57f205cc175527072208ad.html
这道题可以用状态压缩,我们对于每一把钥匙的状态只有两种,获得了或者没有获得,然后就可以用二进制方法表示,例如一共有5把钥匙,我们如果用二进制数01001表示当前状态,就意味着我们已经拥有了第一类钥匙,第四类钥匙(从右往左看),然后我们就可以把此时的状态压缩为一个int了,节省了很多的空间,具体的操作就用位运算实现。
然后就是简单粗暴的dfs过程。
不过有几个点需要注意
① 要加反边。
② 一个位置可能有多个钥匙,注意要用位与运算。
下面给出代码。
1 #include <cstdio> 2 #include <cstdlib> 3 #include <queue> 4 #include <cstring> 5 using namespace std; 6 const int N = 20; 7 8 struct Node{ 9 int x, y, step, state; 10 }; 11 int n, m, p, t, tt, map[N][N][N][N], key[N][N], vis[N][N][1 << 11]; 12 int py[4][2] = {{0, 1}, {0, -1}, {-1, 0}, {1, 0}}; 13 14 inline int bfs(){ 15 queue < Node > q; 16 q.push((Node){1, 1, 0, key[1][1]}); 17 while(!q.empty()){ 18 Node u = q.front(); q.pop(); 19 if (u.x == n && u.y == m) return u.step; 20 for (int i = 0; i < 4; i++){ 21 int x = u.x + py[i][0]; 22 int y = u.y + py[i][1]; 23 if (x > 0 && x <= n && y > 0 && y <= m) 24 if (!map[u.x][u.y][x][y]) continue; 25 else if((map[u.x][u.y][x][y] == -1) || (1 << (map[u.x][u.y][x][y] - 1)) & u.state){ 26 int states = u.state | key[x][y]; 27 if (!vis[x][y][states]){ 28 q.push((Node){x, y, u.step + 1, states}); 29 vis[x][y][states] = 1; 30 } 31 } 32 } 33 } 34 return -1; 35 } 36 37 38 39 int main(){ 40 scanf("%d %d %d",&n, &m, &p); 41 scanf("%d", &t); 42 memset(map, -1, sizeof(map)); 43 for (int i = 0; i < t; i++){ 44 int a, b, c, d, e; 45 scanf("%d %d %d %d %d", &a, &b, &c, &d, &e); 46 map[a][b][c][d] = map[c][d][a][b] = e; 47 } 48 scanf("%d", &tt); 49 for (int i = 0; i < tt; i++){ 50 int a, b, c; 51 scanf("%d %d %d", &a, &b, &c); 52 key[a][b] |= (1 << (c - 1)); 53 } 54 printf("%d", bfs()); 55 return 0; 56 } 57 58 59 /************************************************************** 60 Problem: 1784 61 User: cminus 62 Language: C++ 63 Result: Accepted 64 Time:0 ms 65 Memory:4896 kb 66 ****************************************************************/
时间: 2024-11-10 16:25:49