题目链接:
http://acm.hdu.edu.cn/showproblem.php?pid=1885
解题思路:
状态压缩,使用二进制分别存储每把钥匙是否拥有的状态,然后当遇到门时,查看此时相应的二进制位数上是否有相应的钥匙,如果有,则进队列,继续搜就行了。直到找到终点为止。。。
AC代码:
#include <iostream> #include <cstdio> #include <cstring> #include <queue> using namespace std; struct node{ int x,y,t; int key;//用二进制存4把钥匙 }; const int dx[] = {-1,0,1,0}, dy[] = {0,-1,0,1}; const char key[] = {'b','y','r','g'}; const char door[] = {'B','Y','R','G'}; char maze[110][110]; int vis[110][110][20];//判断在有不同的key的各个位置是否出现过 int n,m; void bfs(int x,int y){ memset(vis,0,sizeof(vis)); queue<node> q; node cur; cur.x = x;cur.y = y;cur.t = 0;cur.key = 0; q.push(cur); vis[cur.x][cur.y][cur.key] = 1; while(!q.empty()){ cur = q.front(); q.pop(); if(maze[cur.x][cur.y] == 'X'){ printf("Escape possible in %d steps.\n",cur.t); return; } //printf("\n%d %d %d %d\n",cur.x,cur.y,cur.t,cur.key); node tmp; for(int i = 0; i < 4; i++){ //cout<<cur.key<<endl; tmp.x = cur.x+dx[i];tmp.y = cur.y+dy[i];tmp.t = cur.t+1;tmp.key = cur.key; //printf("%d %d %d %d\n",tmp.x,tmp.y,tmp.t,tmp.key); if(tmp.x<0 || tmp.x>=n || tmp.y<0 || tmp.y>=m || maze[tmp.x][tmp.y] == '#') continue; if(islower(maze[tmp.x][tmp.y])){ for(int j = 0; j < 4; j++){ if(maze[tmp.x][tmp.y] == key[j]){ //printf("%d %d %d %d11\n",tmp.x,tmp.y,tmp.t,tmp.key); tmp.key |= (1<<j); if(!vis[tmp.x][tmp.y][tmp.key]){ //key记录得到这把钥匙 vis[tmp.x][tmp.y][tmp.key] = 1; q.push(tmp); } break; } } } else if(isupper(maze[tmp.x][tmp.y]) && maze[tmp.x][tmp.y] != 'X'){ //找到对应的门,且有该门的钥匙,且在这种状态下的这个位置未走过 for(int j = 0; j < 4; j++){ if(maze[tmp.x][tmp.y] == door[j] && (tmp.key & (1<<j)) && !vis[tmp.x][tmp.y][tmp.key]){ vis[tmp.x][tmp.y][tmp.key] = 1; q.push(tmp); break; } } } else if(!vis[tmp.x][tmp.y][tmp.key]){ vis[tmp.x][tmp.y][tmp.key] = 1; q.push(tmp); } } } printf("The poor student is trapped!\n"); } int main(){ while(scanf("%d%d",&n,&m),n+m){ for(int i = 0; i < n; i++) scanf("%s",maze[i]); for(int i = 0;i < n; i++) for(int j = 0;j < m; j++){ if(maze[i][j] == '*'){ bfs(i,j); break; } } } return 0; }