(HDU1429)胜利大逃亡(续)-BFS-状态压缩

胜利大逃亡(续)

Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 10925    Accepted Submission(s): 3977


 

Problem Description

Ignatius再次被魔王抓走了(搞不懂他咋这么讨魔王喜欢)……

这次魔王汲取了上次的教训,把Ignatius关在一个n*m的地牢里,并在地牢的某些地方安装了带锁的门,钥匙藏在地牢另外的某些地方。刚开始Ignatius被关在(sx,sy)的位置,离开地牢的门在(ex,ey)的位置。Ignatius每分钟只能从一个坐标走到相邻四个坐标中的其中一个。魔王每t分钟回地牢视察一次,若发现Ignatius不在原位置便把他拎回去。经过若干次的尝试,Ignatius已画出整个地牢的地图。现在请你帮他计算能否再次成功逃亡。只要在魔王下次视察之前走到出口就算离开地牢,如果魔王回来的时候刚好走到出口或还未到出口都算逃亡失败。

 

Input

每组测试数据的第一行有三个整数n,m,t(2<=n,m<=20,t>0)。接下来的n行m列为地牢的地图,其中包括:

. 代表路
* 代表墙
@ 代表Ignatius的起始位置
^ 代表地牢的出口
A-J 代表带锁的门,对应的钥匙分别为a-j
a-j 代表钥匙,对应的门分别为A-J

每组测试数据之间有一个空行。

 

Output

针对每组测试数据,如果可以成功逃亡,请输出需要多少分钟才能离开,如果不能则输出-1。

 

Sample Input

4 5 17 @A.B. a*.*. *..*^ c..b* 4 5 16 @A.B. a*.*. *..*^ c..b*

 

Sample Output

16 -1

题目分析:

题目大意是问能否在有限的时间走出迷宫,在走的过程中,会遇到门,若有对应门的钥匙则可以通过,否则不能。

迷宫问题很容易想到BFS。表示人的状态除了有位置信息x,y和时间信息t,还有钥匙的信息。钥匙最多有10把,每把钥匙有取和不取两种状态,共有2^10种可能的情况,太大了,所以想到状态压缩,用二进制位的0,1来代表取和不取。

代码:

#include<iostream>
#include<string.h>
#include<queue>
using namespace std;
/*
Node:	x,y:位置,step:时间,key:钥匙的状态

p:	四个方向
vis:	标记数组
*/
struct Node {
	int x;
	int y;
	int step;
	int key;
	Node(int a = 0, int b = 0, int c = 0, int d = 0) :x(a), y(b), step(c), key(d) {}
};
int n, m, t;
int sx, sy;
char maze[22][22];
queue<Node> q;
int vis[22][22][1025];
int p[4][2] = { { 1,0 },{ -1,0 },{ 0,1 },{ 0,-1 } };
/*
BFS	
检测是否有该钥匙:	kk >> (maze[xx][yy] - 'A') & 1
获取钥匙:	kk | (1 << (maze[xx][yy] - 'a'))
*/
int bfs() {
	Node temp;
	while (!q.empty())q.pop();
	q.push(Node(sx, sy, 0, 0));
	while (!q.empty())
	{
		temp = q.front();
		q.pop();
		int xx, yy, ss, kk;
		for (int i = 0; i < 4; i++) {
			xx = temp.x + p[i][0];
			yy = temp.y + p[i][1];
			ss = temp.step + 1;
			kk = temp.key;
			if (xx < 0 || xx >= n || yy < 0 || yy >= m)continue;
			if (ss >= t)continue;
			if (vis[xx][yy][kk])continue;
			if (maze[xx][yy] == '*')continue;
			if (maze[xx][yy] == '^')
			{
				return ss;
			}
			if (maze[xx][yy] >= 'A' && maze[xx][yy] <= 'J')
			{
				if (!(kk >> (maze[xx][yy] - 'A') & 1)) {
					continue;
				}
			}
			if (maze[xx][yy] >= 'a'&&maze[xx][yy] <= 'j')
			{
				kk = kk | (1 << (maze[xx][yy] - 'a'));
			}

			vis[xx][yy][kk] = 1;
			q.push(Node(xx, yy, ss, kk));
		}
	}
	return -1;
}


int main() {

	while (cin >> n >> m >> t) {
		memset(vis, 0, sizeof(vis));
		for (int i = 0; i < n; i++)
		{
			for (int j = 0; j < m; j++)
			{
				cin >> maze[i][j];
				if (maze[i][j] == '@') {
					sx = i;
					sy = j;
				}
			}
		}
		cout << bfs() << endl;
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/xiaosi1524/article/details/81866175