HDU 1885 —— Key Task 状压BFS

原题:http://acm.hdu.edu.cn/showproblem.php?pid=1885

题意:问从*到X至少走几步;

    ’ # ‘ 是墙,’ . ‘ 是空地;大写字母是门,小写字母是钥匙,字母相同才可配对,如 b 开 B ,且钥匙一直都在并非开完一扇门钥匙就失效了;


思路:手里拥有钥匙的状态,状压一下,每次走到一个点,判断在已拥有的钥匙的状态下这个点是否走过 vis[i][j][status];


#include<cstdio>
#include<cstring>
#include<string>
#include<queue>

using namespace std;
const int maxn = 110;
char map[maxn][maxn];
bool vis[maxn][maxn][35];
int n, m;
int sx, sy;
int f[4][2] = {-1, 0, 0, -1, 0, 1, 1, 0};

struct node
{
	int x, y;
	int step;
	int key;
};

int Num(char c)
{
	if(c == 'B' || c == 'b')	return 1;
	if(c == 'G' || c == 'g')	return 2;
	if(c == 'R' || c == 'r')	return 3;
	if(c == 'Y' || c == 'y')	return 4;
}

void bfs()
{
	queue<node>q;
	while(!q.empty())	q.pop();
	node a;
	a.x = sx, a.y = sy;
	a.step = 0;
	a.key = 0;
	vis[sx][sy][0] = true;
	q.push(a);
	while(!q.empty())
	{
		node b = q.front();
		q.pop();
		if(map[b.x][b.y] == 'X')
		{
			printf("Escape possible in %d steps.\n", b.step);
			return;
		}
		for(int i = 0;i<4;i++)
		{
			node c;
			int nx = b.x + f[i][0];
			int ny = b.y + f[i][1];
			int key = b.key;
			if(nx < 0 || ny < 0 || nx >= n || ny >= m || map[nx][ny] == '#')	continue;
			if(map[nx][ny] >= 'A' && map[nx][ny] <= 'Z' && !vis[nx][ny][key] && map[nx][ny] != 'X')
			{
				int k = Num(map[nx][ny]);
				if(key & (1 << k))
				{
					vis[nx][ny][key] = true;		
					c.x = nx, c.y = ny, c.key = b.key, c.step = b.step + 1;
					q.push(c);
				}
			}
 			else if(map[nx][ny] >= 'a' && map[nx][ny] <= 'z')
			{
				int k = Num(map[nx][ny]);
				key = key | (1 << k);
				if(!vis[nx][ny][key])
				{
					vis[nx][ny][key] = true;
					c.x = nx, c.y = ny, c.key = key, c.step = b.step + 1;
					q.push(c);
				}
			}
			else
			{
				if(!vis[nx][ny][key])
				{
					vis[nx][ny][key] = true;
					c.x = nx, c.y = ny, c.key = b.key, c.step = b.step + 1;
					q.push(c);
				}
			}
		}
	}
	printf("The poor student is trapped!\n");
	return;
}

int main()
{
	while(~scanf("%d%d", &n, &m))
	{
		if(n == 0 && m == 0)	break;
		for(int i = 0;i<n;i++)
		{
			scanf("%s", map[i]);
			for(int j = 0;j<m;j++)
			{
				if(map[i][j] == '*')
				sx = i, sy = j;
			}
		}
		memset(vis, false, sizeof vis);
		bfs();
	}
	return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值