HDU 5094 maze
题目链接[http://acm.hdu.edu.cn/showproblem.php?pid=5094][6]
题目分析
一个人要在这个星球上的一个位置去另外一个位置救另外一个人,现在有一个地图,如果想从地图一个位置到隔壁四个方向的位置,必须满足:
-
相邻的两个位置之间没有墙
-
如果相邻两个位置之间有门,必须有门的钥匙
需解决的问题:
-
想要从(1,1)–>(n,m)需要找到所有的钥匙,再打开路程中需要打开的门,才能到达
-
钥匙的位置怎么记录
-
怎么记录一个结点和前后左右之间是联通的还是墙还是门(什么类型的门)
-
怎么标记走过的路
解决问题的方法:
-
使用二进制表示方法记录每个钥匙出现的位置
-
使用四维数组记录相邻两个结点之间间隔的内容
-
使用三维vis数组来标记这个位置使用这把钥匙开过门
AC代码
#include<iostream>
#include<queue>
#include<cstring>
using namespace std;
#define N 51
int n,m,p;
int k;
int s;
struct node {
int x;
int y;
int key;
int step;
};
int key[N][N];
int wall[N][N][N][N];
const int dir[4][2] = {0,1,1,0,0,-1,-1,0};
int vis[N][N][1<<10];
void bfs() {
queue<node> que;
node no,n1;
n1.x = 1;
n1.y = 1;
n1.key = 0;
n1.step = 0;
que.push(n1);
while(!que.empty()) {
no = que.front();
que.pop();
if(no.x == n && no.y == m) {
cout<<no.step<<endl;
return;
}
no.key |= key[no.x][no.y];
for(int i=0; i<4; i++) {
int nx = no.x + dir[i][0];
int ny = no.y + dir[i][1];
if(nx>=1&&nx<=n&&ny>=1&&ny<=m) {
int gate = wall[no.x][no.y][nx][ny];
if((gate>0&&(no.key&(1<<(gate-1)))) || gate==-1) {
if(!vis[nx][ny][no.key]) {
vis[nx][ny][no.key] = 1;
n1.x = nx;
n1.y = ny;
n1.key = no.key;
n1.step = no.step + 1;
que.push(n1);
}
}
}
}
}
cout<< -1<<endl;
}
int main() {
int x1,y1,x2,y2,g;
while(cin>>n>>m>>p) {
memset(key,0,sizeof(key));
memset(wall,-1,sizeof(wall));
memset(vis,0,sizeof(vis));
cin>>k;
for(int i=1; i<=k; i++) {
cin>>x1>>y1>>x2>>y2>>g;
wall[x2][y2][x1][y1] = wall[x1][y1][x2][y2] = g;
}
cin>>s;
for(int i=1; i<=s; i++) {
cin>>x1>>y1>>g;
key[x1][y1] |= 1<<(g-1);
}
bfs();
}
return 0;
}