您的位置:首页 > 其它

hdu 5091 Maze (bfs+状态压缩)

2014-12-06 20:43 369 查看
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5094

题意:给定一张格子图,(1,1)为起点,(n,m)为终点,每个节点和它相邻的节点会存在墙和门,其中门有好多种,当到达这个位置的时候如果你没有这个门的钥匙的话,就不能穿过这个门,每种门的钥匙分散在图上的个个地方,问从起点到终点的最短距离。

思路:大bfs,加一维来表示到达每个地方时所获钥匙的状态,dp[x][y][k]表示到达图上x,y这个地方时所获钥匙状态为k时的最短路径,对于每个位置就向四个方向搜救行了,状态转移时要考虑墙和门。

像这样的题目思路大家都知道,就是写起来的时候要注意,每个地方都要思考用尽量好的姿势来做,具体细节看代码~

code:

#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <queue>
#define INF 1000000007
using namespace std;

const int maxn=55;
const int maxe=100000;

int dp[maxn][maxn][1<<11];

//door 为门数组 -1 表示没有障碍物 0 表示存在墙 1~。。 表示存在哪种门 数组的最后一维用来表示方向
//key为钥匙数组 用二进制来表示每个位置都放了那几种钥匙
int door[maxn][maxn][4];
int key[maxn][maxn];
int n,m,q;

int dx[4]={-1,1,0,0};
int dy[4]={0,0,-1,1};

struct node
{
int x,y,st;
node(){};
node(int x,int y,int st): x(x),y(y),st(st){}
};

queue<node> qq;

void bfs(int x,int y)
{
memset(dp,-1,sizeof(dp));
qq.push(node(x,y,0));
dp[x][y][0]=0;
while(qq.size()){
node v=qq.front(); qq.pop();
for(int i=0;i<4;i++){
int mx=v.x+dx[i],my=v.y+dy[i],ms=v.st;
if(mx<1||mx>n||my<1||my>m) continue;
if(door[v.x][v.y][i]==0) continue;
if(door[v.x][v.y][i]==-1||(1<<(door[v.x][v.y][i]-1)&v.st)){
ms|=key[mx][my];
if(dp[mx][my][ms]==-1||dp[mx][my][ms]>dp[v.x][v.y][v.st]+1){
dp[mx][my][ms]=dp[v.x][v.y][v.st]+1;
qq.push(node(mx,my,ms));
}
}
}
}
int res=INF;
for(int i=0;i<(1<<q);i++) if(dp
[m][i]!=-1) res=min(res,dp
[m][i]);
if(res==INF) printf("-1\n");
else printf("%d\n",res);
}
int main()
{
int kk;
int x1,x2,y1,y2,g;
while(scanf("%d%d%d",&n,&m,&q)!=EOF){
memset(door,-1,sizeof(door));
memset(key,0,sizeof(key));
scanf("%d",&kk);
while(kk--){
scanf("%d%d%d%d%d",&x1,&y1,&x2,&y2,&g);
int i;
for(i=0;i<4;i++){
int mx=x1+dx[i],my=y1+dy[i];
if(mx==x2&&my==y2) break;
}
//注意建立双向门
door[x1][y1][i]=g;
door[x2][y2][i^1]=g;
}
scanf("%d",&kk);
while(kk--){
scanf("%d%d%d",&x1,&y1,&g);
key[x1][y1]|=1<<(g-1);
}
bfs(1,1);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: