勝利大逃亡(續) - 狀壓bfs
阿新 • • 發佈:2020-09-17
在之前一題的基礎上加了個條件,也就是說如果當然位置的值是門,那麼需要有鑰匙才能經過。、
按照前一題的思路,進行狀壓,設定vis[][][1 << 10]陣列,表示當前點以及當前資訊是否訪問過。
如果說是小寫字母,也就是鑰匙,就直接把當前狀態或運算一下,讓當前點繼承或後的值,然後加入佇列即可
如果說是大寫字母,也就是門,那麼就需要進行判斷,判斷我對應的鑰匙是否存在,用和運算子號,注意此時,直接繼承之前的資訊即可,不需要把key變成和之後的結果
如果是普通的點,就直接繼承即可
傳送門
#include <iostream> #include <cstdio> #include <queue> #include <cstring> using namespace std; const int N = 25; char s[N][N]; bool vis[N][N][1 << 11]; int dir[][2] = {1, 0, -1, 0, 0, 1, 0, -1}; int n, m, t; int sx, sy, ex, ey; struct Node{ int x, y, key, step; }; bool check(int x, int y){ if(x < 1 || x > n || y < 1 || y > m || s[x][y] == '*') return 0; return 1; } int bfs(){ queue<Node> q; Node now; now.x = sx, now.y = sy, now.key = 0, now.step = 0; q.push(now); while(!q.empty()) { Node u = q.front(); q.pop(); if(u.step >= t) return -1; if(u.x == ex && u.y == ey) return u.step; for(int i = 0; i < 4; i++) { int xx = dir[i][0] + u.x; int yy = dir[i][1] + u.y; if(!check(xx, yy)) continue; Node nex; nex.step = u.step + 1; nex.x = xx, nex.y = yy; nex.key = u.key; if(s[xx][yy] >= 'a' && s[xx][yy] <= 'z') { int temp = s[xx][yy] - 'a'; nex.key = u.key | (1 << temp); }else if(s[xx][yy] >= 'A' && s[xx][yy] <= 'Z') { int temp = s[xx][yy] - 'A'; int key = u.key & (1 << temp); if(!key) continue; } if(vis[xx][yy][nex.key]) continue; vis[xx][yy][nex.key] = 1; q.push(nex); } } return -1; } int main(){ while(~scanf("%d%d%d", &n, &m, &t)) { memset(vis, 0, sizeof(vis)); for(int i = 1; i <= n; i++) scanf("%s", s[i] + 1); for(int i = 1; i <= n; i++) { for(int j = 1; j <= m; j++) { if(s[i][j] == '@') sx = i, sy = j; if(s[i][j] == '^') ex = i, ey = j; } } printf("%d\n", bfs()); } return 0; }