hdu1429 勝利大逃亡(續) (BFS+狀態壓縮)
阿新 • • 發佈:2019-02-17
因為鑰匙最多隻有10個,所以可以用一個10位的二進位制數表示擁有的鑰匙。
key[i][j]表示座標(i,j)上有哪把鑰匙,door[i][j]表示座標(i,j)上有哪扇門。
節點中儲存的狀態除了步數step,座標x,y之外還有目前擁有的鑰匙key。
能否開啟門只需要判斷:
if((key & door[x][y]) == door[x][y]) { /* next */}
拾取鑰匙可以表示為:
node.key | key[nx][ny]
程式碼:
#include <cstdio> #include <cstring> #include <algorithm> #include <iostream> #include <queue> using namespace std; struct Node{ int x; int y; int step; int key; Node() {} Node(int a, int b, int s, int k) : x(a), y(b), step(s), key(k) {} }; int n, m, t; int arr[25][25]; int door[25][25]; int key[25][25]; int Go[4][2] = {{0, 1}, {0, -1}, {-1, 0}, {1, 0}}; int sx, sy; int ex, ey; int vis[25][25][1049]; bool canGo(int x, int y, int k) { if (x >= 0 && x < n && y >= 0 && y < m && !arr[x][y]) { if (vis[x][y][k]) return false; if ((k & door[x][y]) == door[x][y]) return true; } return false; } int bfs() { memset(vis, 0, sizeof(vis)); queue<Node> q; Node s = Node(sx, sy, 0, 0); q.push(s); vis[sx][sy][0] = 1; while (!q.empty()) { Node e = q.front(); q.pop(); if (e.x == ex && e.y == ey) return e.step; for (int i = 0; i < 4; i++) { int nx = e.x + Go[i][0]; int ny = e.y + Go[i][1]; if (canGo(nx, ny, e.key)) { Node nex = Node(nx, ny, e.step + 1, e.key | key[nx][ny]); vis[nx][ny][nex.key] = 1; q.push(nex); } } } return 0; } int main() { while (~scanf("%d %d %d\n", &n, &m, &t)) { memset(arr, 0, sizeof(arr)); memset(door, 0, sizeof(door)); memset(key, 0, sizeof(key)); char c; for (int i = 0; i < n; i++) { for (int j = 0; j < m; j++) { scanf("%c", &c); if (c == '*') arr[i][j] = 1; else if (c == '@') sx = i, sy = j; else if (c == '^') ex = i, ey = j; else if (c >= 'a' && c <= 'z') key[i][j] = 1 << (c - 'a'); else if (c >= 'A' && c <= 'Z') door[i][j] = 1 << (c - 'A'); } getchar(); } int ans = bfs(); if (ans < t && ans) printf("%d\n", ans); else printf("-1\n"); } return 0; }