您的位置:首页 > 其它

hdu 1885 Key Task bfs + 状态压缩

2016-03-29 13:25 288 查看
题目:http://acm.hdu.edu.cn/showproblem.php?pid=1885

思路:有四把钥匙,有16种持有状态,每个点并不是只能走一遍,而是当钥匙持有状态不同时就可以走,有相同的钥匙状态走到相同的点认为是重复。于是开三维数组,其中一维标记钥匙状态,用位运算来计算很方便

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
using namespace std;

int dx[] = {0, 0, -1, 1}, dy[] ={-1, 1, 0, 0};
const int N = 110;
char mpa

;
int step[1<<4]

;
int n, m;
char k1[] = "BYRG", k2[] = "byrg";
bool f;

struct node
{
int state;
int x, y;
};

bool door(int nx, int ny, int state) //能不能打开门
{
if(mpa[nx][ny] >= 'A' && mpa[nx][ny] <= 'Z')
{
for(int i = 0; i < 4; i++)
if(mpa[nx][ny] == k1[i])
{
if((1 << i) & state) return true;
else return false;
}
}
return true;
}

void bfs(int sx, int sy)
{
memset(step, -1, sizeof step);
queue<node> que;
node e;
e.x = sx, e.y = sy, e.state = 0;
step[e.state][e.x][e.y] = 0;
que.push(e);

while(! que.empty())
{
e = que.front(); que.pop();
if(mpa[e.x][e.y] == 'X')
{
printf("Escape possible in %d steps.\n", step[e.state][e.x][e.y]);
f = true;
break;
}

for(int i = 0; i < 4; i++)
{
int nx = e.x + dx[i], ny = e.y + dy[i];
if(nx >= 0 && nx < n && ny >= 0 && ny < m && mpa[nx][ny] != '#' && door(nx, ny, e.state) && step[e.state][nx][ny] == -1) //钥匙状态相同不能再走相同点
{
int newstate = e.state;
if(mpa[nx][ny] >= 'a' && mpa[nx][ny] <= 'z') //拿起钥匙
{
for(int i = 0; i < 4; i++)
if(mpa[nx][ny] == k2[i])
newstate |= (1<<i);
}

node tmp;
tmp.state = newstate, tmp.x = nx, tmp.y = ny;
step[newstate][nx][ny] = step[e.state][e.x][e.y] + 1;
que.push(tmp);
}
}
}
}

int main()
{
int sx, sy;
while(scanf("%d%d", &n, &m), n || m)
{
f = false;
for(int i = 0; i < n; i++)
{
scanf(" %s", mpa[i]);
for(int j = 0; mpa[i][j]; j++)
if(mpa[i][j] == '*') sx = i, sy = j;
}

bfs(sx, sy);
if(! f) printf("The poor student is trapped!\n");
}

return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: