题意
给一个图,问最少需要多少步可以逃出去。
*:起点
#:墙,不走能
.:路
X:出口
b,y,r,g:对应每个大写字母的钥匙
B,Y,R,G:对应颜色的门,需要有对应颜色的钥匙才能打开
每个钥匙可以打开多扇同颜色的门,可能有多个出口。
思路
求最短路,用BFS。因为为了拿钥匙,会重复走某一个地方,所以不能用二维数组vis记录走没走过;用三维数组记录在某个点时是否有某种颜色的钥匙。
在记录走到某点是否有某钥匙的时候遇到了困难,死活做不出来,看了题解之后是使用了状态压缩:用k = 0,1,2,3分别表示b,y,r,g这四种颜色的钥匙,1<<k表示颜色为k的钥匙,用此点的所拥有的钥匙颜色key与1<<k按位与进行比较,如果等于0,就是没有这种颜色的钥匙。
(按位与:参与运算的两数各对应的二进位相与。只要对应的二个二进位都为1时,结果位就为1。eg: key = 1100,对应的十进制为12,即拥有2, 3两种颜色的钥匙,若与1<<2比较,即十进制下12 & 4,结果不为0,即此点有这种颜色的钥匙)
总结
1. 初步了解了状压,终于明白了按位与的作用,开心啊,不错不错,233
2. 比原来更了解了一些bfs,将在某点可走的方向都存入队列中,下一次又是另一个点可走的方向存入进去,如果某个方向走不通,就都弹出了队列。刚开始觉得有好几个出口应该找好几次,然后输出最小的那个,现在知道了只要通过一次bfs就能找到最短的那条路,而不是多次
1 #include <iostream> 2 #include <cstdio> 3 #include <algorithm> 4 #include <cstring> 5 #include <string> 6 #include <queue> 7 #include <cctype> 8 using namespace std; 9 const int maxn = 105; 10 int n, m; 11 char G[maxn][maxn]; 12 int vis[maxn][maxn][35]; 13 const int dr[] = {-1, 0, 1, 0}; 14 const int dc[] = { 0, 1, 0,-1}; 15 16 struct Node 17 { 18 int r, c, key, step; 19 Node(int r = 0, int c = 0, int key = 0, int step = 0):r(r), c(c), key(key), step(step){} 20 }; 21 22 int getColor(char key) 23 { 24 key = tolower(key); 25 if(key == 'b') return 0; 26 else if(key == 'y') return 1; 27 else if(key == 'r') return 2; 28 else if(key == 'g') return 3; 29 } 30 31 bool isInside(int r, int c) 32 { 33 if(r > 0 && r <= n && c > 0 && c <= m && G[r][c] != '#') 34 return true; 35 else 36 return false; 37 } 38 39 void bfs(int rr, int cc) 40 { 41 queue<Node> q; 42 memset(vis, 0, sizeof vis); 43 Node node(rr, cc, 0, 0); 44 q.push(node); 45 while(!q.empty()) { 46 Node u = q.front(); 47 q.pop(); 48 if(G[u.r][u.c] == 'X') { 49 printf("Escape possible in %d steps.\n", u.step); 50 return; 51 } 52 for(int i = 0; i < 4; i++) { 53 Node v(u.r + dr[i], u.c + dc[i], u.key, u.step+1); 54 if(isInside(v.r, v.c)) { 55 if(islower(G[v.r][v.c])) { 56 int k = getColor(G[v.r][v.c]); 57 if((v.key & (1 << k)) == 0) { //如果没有这种颜色的钥匙 58 v.key += (1 << k); //把这种颜色的钥匙加入进去 59 } 60 if(!vis[v.r][v.c][v.key]) { 61 vis[v.r][v.c][v.key] = 1; 62 q.push(v); 63 } 64 } 65 else if(isupper(G[v.r][v.c]) && G[v.r][v.c] != 'X') { 66 int k = getColor(G[v.r][v.c]); 67 if(v.key & (1 << k) && !vis[v.r][v.c][v.key]) { 68 vis[v.r][v.c][v.key] = 1; 69 q.push(v); 70 } 71 } 72 else { 73 if(!vis[v.r][v.c][v.key]) { 74 vis[v.r][v.c][v.key] = 1; 75 q.push(v); 76 } 77 } 78 } 79 } 80 } 81 printf("The poor student is trapped!\n"); 82 } 83 int main() 84 { 85 freopen("in.txt", "r", stdin); 86 while(scanf("%d %d", &n, &m) && n) { 87 memset(G, '#', sizeof G); 88 int x, y; 89 for(int i = 1; i <= n; i++) { 90 scanf("%s", G[i]+1); 91 G[i][m+1] = '#'; 92 G[i][m+2] = '\0'; 93 if(strchr(G[i], '*')) { 94 x = i; 95 y = strchr(G[i], '*') - *G - i*105; 96 } 97 } 98 //printf("%d %d\n", x, y); 99 bfs(x, y); 100 } 101 return 0; 102 }