题目:http://acm.hdu.edu.cn/showproblem.php?pid=1885
题目意思:给出一个n*m的迷宫,各种字符的含义可以参考题目所给的表格,移动只能往上下左右,问能否从*出发到达X,*只有一个,但X可能有多个,如果能,输出最少步数,不能则要输出另一句信息。
还是比较经典的迷宫题目,只是在这个基础上加上了门和钥匙,所以在搜索的时候要记录上钥匙的状态。由于门最多4种,所以可以用4个二进制位来表示是否带有对应的钥匙,所以钥匙的状态有2^4=16种,地图100*100,所以总状态数最多160000。采用广搜写法,细心点码就能AC。
#include<cstdio> #include<cstring> #include<queue> using namespace std; struct Point{ int x, y, s, u; }p; int xl[4]={-1,1,0,0}; int yl[4]={0,0,-1,1}; int n, m, i, j, x, y, a, b; char map[100][110]; bool vis[100][100][1<<4]; int idx(char ch){ if(ch=='b') return 0; if(ch=='y') return 1; if(ch=='r') return 2; return 3; } int main(){ while(~scanf("%d %d", &n, &m) && (n||m)){ memset(vis,0,sizeof(vis)); for(i=0; i<n; i++){ scanf("%s", map[i]); for(j=0; j<m; j++){ if(map[i][j]=='*'){ x=i; y=j; break; } } } queue<Point> Q; Q.push((Point){x,y,0,0}); vis[x][y][0]=1; bool flag=0; while(!Q.empty()){ p=Q.front();Q.pop(); x=p.x; y=p.y; p.u++; for(i=0; i<4; i++){ a = x+xl[i]; b = y+yl[i]; if(a<0 || a>=n || b<0 || b>=m) continue; if(map[a][b]=='X'){ printf("Escape possible in %d steps.\n", p.u); flag=1; break; } if(map[a][b]=='#') continue; if(map[a][b]>='A' && map[a][b]<='Z'){ j = idx(map[a][b]-'A'+'a'); if(!(p.s&(1<<j))) continue; j = p.s; } else if(map[a][b]>='a' && map[a][b]<='z'){ j = idx(map[a][b]); j = p.s | (1<<j); } else j=p.s; if(vis[a][b][j]) continue; vis[a][b][j]=1; Q.push((Point){a,b,j,p.u}); } if(flag) break; } if(!flag) puts("The poor student is trapped!"); } return 0; }