zoukankan      html  css  js  c++  java
  • hdu 1072 广搜(逃离爆炸迷宫)

    题意:

    在n×m的地图上,0表示墙,1表示空地,2表示人,3表示目的地,4表示有定时炸弹重启器。定时炸弹的时间是6,人走一步所需要的时间是1。每次可以上、下、左、右移动一格。当人走到4时如果炸弹的时间不是0,可以重新设定炸弹的时间为6。如果人走到3而炸弹的时间不为0时,成功走出。求人从2走到3的最短时间。这个题中每个结点都是可以重复访问的,但其实,炸弹重置点不要重复走,因为,走到炸弹重置点时时间就会被设置为最大时间,当重新返回时时间又设成最大,但此时已走的步数肯定增加了,所以如果存在较优解的话那么肯定在第一次到这点后就可以找到较优解,这也是代码中剪枝的原理,只是将这种思想扩展到普通点而已,所以采用记忆化搜。

    代码:

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <queue>
    
    using namespace std;
    
    const int MAX=10;
    
    typedef struct point     //每个单元信息
    {
        int x,y;             //坐标
        int step;            //走到这里的步数
        int time;            //还剩多少时间
    }Point;
    
    Point cur,nxt;
    
    int mmap[MAX][MAX];
    int n,m;
    int si,sj;
    int dx[]={-1,1,0,0};    //方向
    int dy[]={0,0,-1,1};
    
    void bfs()              //广搜
    {
        queue<Point> q;
        cur.time=6;
        cur.step=0;
        cur.x=si;
        cur.y=sj;
        q.push(cur);            //把起点压入队列中
        while(!q.empty())
        {
            cur=q.front();
            q.pop();
            for(int i=0;i<4;i++)        //四个方向搜索
            {
                nxt.x=cur.x+dx[i];
                nxt.y=cur.y+dy[i];
                nxt.time=cur.time-1;      //时间-1
                nxt.step=cur.step+1;      //步数+1
                if(nxt.x<0||nxt.x>=n||nxt.y<0||nxt.y>=m) continue;          //如果当前点的坐标超出迷宫范围  直接下一个方向搜索
                if(mmap[nxt.x][nxt.y]==1)
                {
                    if(nxt.time>0)
                    {
                        q.push(nxt);
                    }
                }
                else if(mmap[nxt.x][nxt.y]==3)
                {
                    if(nxt.time>0)
                    {
                        cout<<nxt.step<<endl;
                        return;
                    }
                }
                else if(mmap[nxt.x][nxt.y]==4)
                {
                    if(nxt.time>0)
                    {
                        nxt.time=6;
                        mmap[nxt.x][nxt.y]=0;         //遇到能重置时间的点,要把它置成墙,因为如果不这样会造成死循环。并且如果第二次走到这里时间都是一样,但步数会增加。
                        q.push(nxt);
    
                    }
                }
            }
        }
        cout<<-1<<endl;
    }
    
    int main()
    {
        int Case;
        cin>>Case;
        while(Case--)
        {
    
            memset(mmap,0,sizeof(mmap));
            cin>>n>>m;
            for(int i=0;i<n;i++)
            {
                for(int j=0;j<m;j++)
                {
                    cin>>mmap[i][j];
                    if(mmap[i][j]==2)
                    {
                        si=i,sj=j;           //纪录起点坐标。
                    }
                }
            }
            bfs();
    
        }
        return 0;
    }
    

      

    人生如修仙,岂是一日间。何时登临顶,上善若水前。
  • 相关阅读:
    react中实现滚动到指定位置固定显示导航栏,反之浸入背景
    activeElement解决ios滚动到底部显示内容时,键盘挡住显示内容的问题
    公积金无租房备案提取如何办理?(以成都为例)
    公积金状态封存怎么解封?
    你应该知道的公积金基础知识科普
    react antd表单不用form.create方法怎么设置input 回显值
    简述个人账户向公司账户转账的方法
    js拖拽进入和离开重复触发的问题
    Electron截屏功能
    Electron在mac下快捷键失效的问题及解决
  • 原文地址:https://www.cnblogs.com/f-society/p/6734714.html
Copyright © 2011-2022 走看看