Key Task
题目链接:
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;
}