您的位置:首页 > 其它

HDOJ 1429 胜利大逃亡(续)(BFS + 状态压缩)

2016-08-07 23:24 309 查看


胜利大逃亡(续)

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

解题思路:由于只有10把钥匙,所以可以进行状态压缩,使用三维数组保存状态。这道题有一个和HDOJ1253相同的坑点,就是bfs函数的返回值问题,因为这个WA了几次。。。

补充(位运算实现技巧):

如果要获得第i位的数据,判断((data&(0X1<<i))==0),若真,为0,假,为1; 

如果要设置第i位为1,data=(data|(0X1<<i)); 

如果要设置第i位为0,data=(data&(~(0X1<<i))); 

如果要将第i位取反,data=(data^(0X1<<i); 

如果要取出一个数的最后一个1(lowbit):(data&(-data))         (这里利用的是负数取反加1实际上改变的是二进制最低位的1这个性质)

代码如下:

#include <algorithm>
#include <cctype>
#include <climits>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <map>
#include <queue>
#include <set>
#include <stack>
#include <vector>
#define EPS 1e-6
#define INF INT_MAX / 10
#define LL long long
#define MOD 100000000
#define PI acos(-1.0)

struct node
{
int x;
int y;
int time;
int keys;
};

const int maxn = 22;
const int maxm = 22;
const int maxkey = (1 << 10) + 5;
char maze[maxn][maxm];
int dir[4][2] = {{0,1},{-1,0},{0,-1},{1,0}};
int state[maxn][maxm][maxkey];
int sx,sy;
int ex,ey;
int n,m,t;

int bfs()
{
memset(state,0,sizeof(state));
node p;
p.x = sx,p.y = sy,p.time = 0,p.keys = 0;
std::queue<node> que;
que.push(p);
state[p.x][p.y][p.keys] = 1;
while(que.size()){
node q;
q = que.front();
que.pop();
if(q.x == ex && q.y == ey)
return q.time;
for(int i = 0;i < 4;i++){
node r;
r.x = q.x + dir[i][0];
r.y = q.y + dir[i][1];
r.keys = q.keys;
if(0 <= r.x && r.x < n && 0 <= r.y && r.y < m && maze[r.x][r.y] != '*' && !state[r.x][r.y][r.keys] ){
if('A' <= maze[r.x][r.y] && maze[r.x][r.y] <= 'J'){
int door = maze[r.x][r.y] - 'A';
if(r.keys & (1 << door)){
r.time = q.time + 1;
que.push(r);
state[r.x][r.y][r.keys] = 1;
}
}
else if('a' <= maze[r.x][r.y] && maze[r.x][r.y] <= 'j'){
int key = maze[r.x][r.y] - 'a';
key = 1 << key;
if(!state[r.x][r.y][r.keys | key]){
r.keys |= key;
r.time = q.time + 1;
que.push(r);
state[r.x][r.y][r.keys] = 1;
}
}
else{
r.time = q.time + 1;
que.push(r);
state[r.x][r.y][r.keys] = 1;
}
}
}
}
return t;
}

int main()
{
while(scanf("%d %d %d",&n,&m,&t) != EOF){
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] == '@'){
sx = i;
sy = j;
}
if(maze[i][j] == '^'){
ex = i;
ey = j;
}
}
}
int ans = bfs();
printf("%d\n",ans < t ? ans : -1);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  HDOJ