1147.木乃伊迷宫
时限:1000ms 内存限制:10000K 总时限:3000ms
描述
木乃伊地下宫殿是一个6行6列的迷宫。游戏在木乃伊所在的迷宫里展开,任务就是尽快赶到出口。你一次只能走一步,而木乃伊可以走两步,但木乃伊是很笨的,他总是先尽量跟你达到同一列,如果已经是同一列了,他才会向你走来,有墙的地方人和木乃伊都不能过,你可以利用障碍物牵制住木乃伊。
输入
先输入墙的数量n,然后在后续的n行里每行有3个数表示一堵墙,3个数分别为格子的行、列和墙的位置(0表示这个格子的下方是墙,1表示这个格子的右方是墙),再下来的3行每行2个数,分别表示木乃伊、人还有出口的位置。
输出
如果能安全逃生则输出Yes,否则输出No,答案占一行。
代码:
#include<iostream>
#include<queue>
using namespace std;
int maze[6][6][2];//用来存储迷宫信息。
int n;//墙的数量
typedef struct node{//定义节点结构体
int px,py;
int mx,my;
int useful;//判断这个节点是否有效
};
node start,target;//定义起始点和终点
queue<node>q;//用作bfs的队列
int visited[6][6][6][6];//避免重复访问
int direction[4][2]={//往哪个方向走,相应的x,y都要变化
0,-1,//左面
1,0,//前面
0,1,//右面
-1,0//后面
};
bool iswall(int x,int y,int i);//判断在(x,y)这个格子往i方向走是否是墙的函数
bool bfs();//核心函数
node tonext(node present,int i);//扩展函数,在当前节点上求与之相邻的有效的下一个结点
int main(){
cin>>n;
int i,j,k;
for(int x=0;x<n;x++){
cin>>i>>j>>k;
maze[i][j][k]=1;
}
cin>>start.px>>start.py;
cin>>start.mx>>start.my;
cin>>target.px>>target.py;//输入完毕
visited[start.px][start.py][start.mx][start.my]=1;//起始节点已被访问
q.push(start);//将起始节点加入队列
if(bfs()){
cout<<"YES"<<endl;
}
else{
cout<<"NO"<<endl;
}
return 0;
}
/*
广度遍历的大致思路都差不多,首先是访问队列头部,并将其出队列,看此节点是否为我们的目标节点,
如果是,则返回,如果不是,则拓展。拓展后的结点如果符合条件,就入队。
*/
bool bfs(){
while(!q.empty()){
node top_node=q.front();//取出栈顶
q.pop();
//开始扩展
//先判断栈顶元素是否是出口,若是,则返回true,否则继续扩展
if(top_node.px==target.px &&top_node.py==target.py){
return true;
}
for(int i=0;i<4;i++){
node next_node=tonext(top_node,i);
if(next_node.useful==1){
q.push(next_node);
}
}
}
}
node tonext(node present,int i)//i=0代表向左走,i=1表示向前走,i=2表示向右走,i=3表示向后走
{
node next_node;
next_node.px=present.px+direction[i][0];//更新人的位置
next_node.py=present.py+direction[i][1];
if(next_node.px<0||next_node.px>5||next_node.py<0||next_node.py>5||iswall(present.px,present.py,i)){//判断人的位置是否有效
next_node.useful=0;//如果人在这个方向走不通,则直接返回。
return next_node;
}
else{
next_node.mx=present.mx;//木乃伊更新前的位置信息
next_node.my=present.my;
for(int s=0;s<2;s++){//木乃伊可以走两步,每走一步就判断一次,总是先是跟人在同一列,然后再去同一行。
if(next_node.my<next_node.py &&!iswall(next_node.mx,next_node.my,2)){
next_node.my++;}
else if(next_node.my >next_node.py&&!iswall(next_node.mx,next_node.my,0)){
next_node.my--;
}
else if(next_node.my==next_node.py){
if(next_node.mx<next_node.px&&!iswall(next_node.mx,next_node.my,1)){
next_node.mx++;
}
else if(next_node.mx>next_node.px&&!iswall(next_node.mx,next_node.my,3)){
next_node.mx--;
}
else if(next_node.mx==next_node.px){
next_node.useful=0;
return next_node;
}
}
}
if(next_node.mx==next_node.px&&next_node.my==next_node.py){//更新完木乃伊的位置之后,在判断一下是否此刻木乃伊走到了人的位置,如果是,则直接返回
next_node.useful=0;
return next_node;
}
if(visited[next_node.px][next_node.py][next_node.mx][next_node.my]==1){//如果更新完之后的点曾经已经访问过,则无效,相当于绕了一个大圈,又回到了曾经走过的点
next_node.useful=0;
return next_node;
}
else{
visited[next_node.px][next_node.py][next_node.mx][next_node.my]=1;//否则的话,将这点记录为已访问,将结点置为有效。
next_node.useful=1;
}
}
}
bool iswall(int x,int y,int i){
switch(i)
{
case 0:
return maze[x][y-1][1];
case 1:
return maze[x-1][y][0];
case 2:
return maze[x][y][1];
case 3:
return maze[x][y][0];
}
return 0;
}
//----参考 夏至夏至520----//