HDU 1429 勝利大逃亡(續) (BFS)
阿新 • • 發佈:2018-12-15
思路來自上面這篇大佬的題解,解題思路源自上面這篇題解
- 解題關鍵在於:如何表示是否帶了鑰匙
- 一共有10把鑰匙,共有1024種狀態,用二進位制表示
j | i | h | g | f | e | d | c | b | a |
- 每個點包括:橫座標、縱座標、到達該點的時間、到達該點時帶的鑰匙的狀態
- 定義一個judge函式,用於判斷下一個點是否能走,不能超過邊界,不能是牆,不能超過t(不包括t),帶著當前鑰匙狀態沒有訪問過該點
- bfs(起點,終點)
- 滿足judge的情況下,如果遇到鑰匙a-j,就 |(或)對應的二進位制數,攜帶上鑰匙。如果遇到門,就用當前帶的鑰匙狀態&(與)門對應的二進位制數,試能不能開門。不能開門就continue.
#include<stdio.h> #include<string.h> #include<queue> using namespace std; #define maxn 20 char map1[maxn+5][maxn+5]; int visit[maxn+5][maxn+5][1030]; int n,m,t; int zx[]={0,0,-1,1}; int zy[]={-1,1,0,0}; struct zuobiao { int x; int y; int time; int key; }in,out; bool judge(zuobiao p) { if(p.x>=0&&p.x<n&&p.y>=0&&p.y<m&&map1[p.x][p.y]!='*'&&p.time<t) { if(!visit[p.x][p.y][p.key]) return true; else return false; } else return false; } void bfs(zuobiao f,zuobiao g) { queue<zuobiao>q; f.time=0; f.key=0; q.push(f); visit[f.x][f.y][0]=1; while(!q.empty()) { f=q.front(); q.pop(); zuobiao lu; for(int i=0;i<4;i++) { lu=f; lu.x+=zx[i]; lu.y+=zy[i]; lu.time++; if(judge(lu)) { int x=1; if(map1[lu.x][lu.y]>='a'&&map1[lu.x][lu.y]<='z') { x=x<<(map1[lu.x][lu.y]-'a'); lu.key=lu.key|x; } else if(map1[lu.x][lu.y]>='A'&&map1[lu.x][lu.y]<='Z') { if(!(lu.key&(x<<(map1[lu.x][lu.y]-'A')))) continue; } visit[lu.x][lu.y][lu.key]=1; q.push(lu); if(lu.x==g.x&&lu.y==g.y) { printf("%d\n",lu.time); return ; } } } if(q.empty()) printf("-1\n"); } } int main() { while(scanf("%d %d %d",&n,&m,&t)!=EOF) { memset(visit,0,sizeof(visit)); char s; for(int i=0;i<n;i++) { scanf("%c",&s); for(int j=0;j<m;j++) { scanf("%c",&map1[i][j]); if(map1[i][j]=='@') { in.x=i; in.y=j; } else if(map1[i][j]=='^') { out.x=i; out.y=j; } } } visit[in.x][in.y][0]=1; bfs(in,out); } return 0; }