HDU 1885 —— Key Task(搜索,bfs)

时间:2023-01-03 16:10:11

题目: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;
}