题目链接
- 题意:
输入R×C大小的地图,其中’*‘表示起点位置,’#‘表示不可以通过,’.'表示可以通过,‘B’,‘Y’,‘R’,'G’分别表示蓝、黄、红、绿门,‘b’,‘y’,‘r’,'g’分别表示蓝、黄、红、绿门的钥匙,'X’表示出口,注意输入数据可能含有零个或多个出口,可能含有多个相同颜色的门或钥匙,可能存在无匹配的钥匙\门的情况,要求计算从起点到终点的最短路径。
- 思路:
由于可能出现同一结点在不同时间可以被多次访问、多个相同颜色的钥匙、钥匙\门不匹配的情况,所以不能仅仅通过记录钥匙的数量来标记结点,而应记录每个结点钥匙的持有情况(共2^4=16种)。为了操作方便与减少空间消耗,进行状态压缩,用一个二进制数来表示钥匙的持有状况,故为标记数组增加一维用来记录结点的钥匙持有情况即可完成标记。
- 二进制数操作回顾:
int GetBit(char c,int i)
{
return (c>>i)&1;
}
void SetBit(char &c,int i,int v)
{
if(v)
c|=(1<<i);
else
c&=~(1<<i);
}
void Flip(char &c,int i)
{
c^=(1<<i);
}
#include <iostream>
#include <cstring>
#include <cstdio>
#include <cstdlib>
#include <queue>
#include <cmath>
#include <map>
using namespace std;
map<char,int> m;
int d[4][2]={{1,0},{-1,0},{0,-1},{0,1}};
char color[]={'B','Y','R','G'};
char colorkeys[]={'b','y','r','g'};
char maze[110][110];
bool reach[110][110][20];
int r,c;
struct s{
int x;
int y;
int steps;
int keys;
s(){}
s(int xx,int yy,int ss,int k):x(xx),y(yy),steps(ss),keys(k){}
};
bool Range(int x,int y,int &k){
if(x<0||y<0||x>=r||y>=c||maze[x][y]=='#')
return false;
if(islower(maze[x][y])){
int i=m[maze[x][y]];
k=k|(1<<i);
if(!reach[x][y][k])
return true;
}
else if(isupper(maze[x][y])&&maze[x][y]!='X'){
int i=m[maze[x][y]];
int j=k&(1<<i);
if(j&&!reach[x][y][k])
return true;
}
else if(!reach[x][y][k])
return true;
return false;
}
int main()
{
std::ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
m['B']=0;m['Y']=1;m['R']=2;m['G']=3;
m['b']=0;m['y']=1;m['r']=2;m['g']=3;
while(cin>>r>>c){
if(r==0&&c==0)
break;
s s0;
memset(reach,0,sizeof(reach));
bool flag=false;
for(int i=0;i<r;i++){
for(int j=0;j<c;j++){
cin>>maze[i][j];
if(maze[i][j]=='X')
flag=true;
if(maze[i][j]=='*'){
s0=s(i,j,0,0);
}
}
}
if(!flag){
cout<<"The poor student is trapped!"<<endl;
continue;
}
queue<s> q;
q.push(s0);
reach[s0.x][s0.y][0]=1;
bool f=false;
while(!q.empty()){
s t=q.front();
q.pop();
if(maze[t.x][t.y]=='X'){
cout<<"Escape possible in "<<t.steps<<" steps."<<endl;
f=true;
break;
}
for(int i=0;i<4;i++){
int kk=t.keys;
int dx=t.x+d[i][0];
int dy=t.y+d[i][1];
if(Range(dx,dy,kk)){
reach[dx][dy][kk]=1;
q.push(s(dx,dy,t.steps+1,kk));
}
}
}
if(!f)
cout<<"The poor student is trapped!"<<endl;
}
return 0;
}