【NOJ1147】【算法实验三】木乃伊迷宫

1147.木乃伊迷宫

时限:1000ms 内存限制:10000K 总时限:3000ms
描述
木乃伊地下宫殿是一个6行6列的迷宫。作为敢到木乃伊地下宫殿里去探险的你,有没有跟木乃伊抓迷藏的心理准备呵!游戏在木乃伊所在的迷宫里展开,任务就是尽快赶到出口。你一次只能走一步,而木乃伊可以走两步,但木乃伊是很笨的,他总是先尽量跟你达到同一列,如果已经是同一列了,他才会像你走来,有墙的地方人和木乃伊都不能过,你可以利用障碍物牵制住木乃伊。

输入
先输入墙的数量n,然后在后续的n行里每行有3个数表示一堵墙,3个数分别为格子的行、列和墙的位置(0表示这个格子的下方是墙,1表示这个格子的右方是墙),再下来的3行每行2个数,分别表示木乃伊、人还有出口的位置。

输出
如果能安全逃生则输出Yes,否则输出No,答案占一行。

输入样例
5
0 0 0
1 1 1
1 4 1
3 4 1
4 3 0
3 3
3 1
5 5

输出样例
No

#include <iostream>
#include <queue>
 
using namespace std;
 
int n;
 
int maze[6][6][2];  //存储迷宫的墙
 
struct node
{
    int mx,my;  //木乃伊位置
    int px,py;  //人位置
    bool useful;    //这个节点是否有效
};                  //无效条件:越界、重复、被抓
 
node start,target;
 
queue <node> q1;
 
int used[6][6][6][6];   //判重
 
int walk[4][2]=     //返回人走一格的新位置坐标
{
    0, -1,  //左
    +1, 0,  //下
    0, +1,  //右
    -1, 0   //上
};
 
void input();   //输入函数
 
bool bfs();
 
node moveto(node cur, int i);   //返回节点cur扩展的下一个节点next
 
bool isWall(int x, int y, int i);   //判断方格[x,y]方向是否是墙
 
int main()
{
    input();
 
    if(bfs())
    {
        cout<<"Yes"<<endl;
    }
    else
    {
        cout<<"No"<<endl;
    }
    return 0;
}
 
void input()
{
    //第一行
    cin>>n;
 
    //第二行
    int i,j,x;
    for(int k=0; k<n; k++)
    {
        cin>>i>>j>>x;
        maze[i][j][x]=1;    //1代表是墙
    }
 
    //最后三行
    cin>>start.mx>>start.my;
    cin>>start.px>>start.py;
    cin>>target.px>>target.py;
 
    //初始节点标记并入队
    used[start.mx][start.my][start.px][start.py]=1;
    q1.push(start);
}
 
bool bfs()
{
    node cur,next;
    while(!q1.empty())
    {
        cur=q1.front();
        q1.pop();
 
        for(int i=0; i<4; i++)  //人要向四个方向试探
        {
            next=moveto(cur, i);    //获取扩展得到的下一个节点
            if(next.useful==true)   //若该节点有效
            {
                if(next.px==target.px&&next.py==target.py)  //若到达目标则返回true
                {
                    return true;
                }
                else    //未到达目标则入队
                {
                    q1.push(next);
                }
            }
        }
    }
    return false;   //所有情况都不能到达目标,返回false
}
 
//该函数返回节点cur扩展的新节点next
//人要向i方向走一步,木乃伊要向人靠近两步
//节点无效条件:人越界、人撞墙、人被木乃伊抓到、节点next重复
node moveto(node cur, int i)
{
    node next;
 
    //人向i方向走一步
    next.px=cur.px+walk[i][0];  //获取新坐标
    next.py=cur.py+walk[i][1];
 
    if((next.px<0||next.px>=6||next.py<0||next.py>=6)   //若人越界
       ||
       (isWall(cur.px, cur.py, i)))             //若撞墙
        {
            next.useful=false;  //该节点无效,直接返回
            return next;
        }
 
    //木乃伊走两步
    next.mx=cur.mx;
    next.my=cur.my;
 
    int step=2;
    while(step--)
    {
        //若列数不相等,则先到达同一列
        if(next.py>next.my&&!isWall(next.mx, next.my, 2))
        {
            next.my++;
        }
        else if(next.py<next.my&&!isWall(next.mx, next.my, 0))
        {
            next.my--;
        }
        //若列数相等,则再到达同一行
        else if(next.py==next.my)
        {
            if(next.px>next.mx&&!isWall(next.mx, next.my, 1))
            {
                next.mx++;
            }
            else if(next.px<next.mx&&!isWall(next.mx, next.my, 3))
            {
                next.mx--;
            }
            //若同行同列,则人被抓住,此节点无效,直接返回
            else if(next.px==next.mx)
            {
                //cout<<next.px<<' '<<next.py<<"catch"<<endl;
                next.useful=false;
                return next;
            }
        }
    }
 
    //人和木乃伊都走完了
    if(used[next.mx][next.my][next.px][next.py])    //若节点重复,则节点无效
    {
        //cout<<next.px<<' '<<next.py<<"used"<<endl;
        next.useful=false;
    }
    else
    {
        used[next.mx][next.my][next.px][next.py]=1; //否则标记该节点到达过
        next.useful=true;                           //标记该节点有效
    }
 
    return next;
}
 
//判断方格[x,y]方向是否是墙
bool isWall(int x, int y, int i)
{
    switch(i)
    {
        case 0:     //向左走
            return maze[x][y-1][1]; //判断左边的方格的右侧是否是墙
 
        case 1:     //向下走
            return maze[x][y][0];   //判断本格的下侧是否是墙
 
        case 2:     //向右走
            return maze[x][y][1];   //判断本格的右侧是否是墙
 
        case 3:     //向上走
            return maze[x-1][y][0]; //判断上边的方格的下侧是否是墙
    }
    return -1;  //返回-1代表i值错误
}
  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值