• DFS中的奇偶剪枝(技巧)


    剪枝是什么,简单的说就是把不可行的一些情况剪掉,例如走迷宫时运用回溯法,遇到死胡同时回溯,造成程序运行时间长。剪枝的概念,其实就跟走迷宫避开死胡同差不多。若我们把搜索的过程看成是对一棵树的遍历,那么剪枝顾名思义,就是将树中的一些“死胡同”,不能到达我们需要的解的枝条“剪”掉,以减少搜索的时间。

    这里介绍一下奇偶剪枝

    什么是奇偶剪枝?

    部分内容来自https://blog.csdn.net/chyshnu/article/details/6171758

    把矩阵看成如下形式: 
    0 1 0 1 0 1 
    1 0 1 0 1 0 
    0 1 0 1 0 1 
    1 0 1 0 1 0 
    0 1 0 1 0 1 
    从为 0 的格子走一步,必然走向为 1 的格子 。
    从为 1 的格子走一步,必然走向为 0 的格子 。
    即: 
    从 0 走向 1 必然是奇数步,从 0 走向 0 必然是偶数步。

    所以当遇到从 0 走向 0 但是要求时间是奇数的或者 从 1 走向 0 但是要求时间是偶数的,都可以直接判断不可达!

     

    比如一张地图c

     
    1. S...  
    2. ....  
    3. ....  
    4. ....  
    5. ...D  

    要求从S点到达D点,此时,从S到D的最短距离为s = abs ( dx - sx ) + abs ( dy - sy )。

    如果地图中出现了不能经过的障碍物:

    1. S..X  
    2. XX.X  
    3. ...X  
    4. .XXX  
    5. ...D  

    此时的最短距离s' = s + 4,为了绕开障碍,不管偏移几个点,偏移的距离都是最短距离s加上一个偶数距离。

    就如同上面说的矩阵,要求你从0走到0,无论你怎么绕,永远都是最短距离(偶数步)加上某个偶数步;要求你从1走到0,永远只能是最短距离(奇数步)加上某个偶数步。

     

    例题

     

    Tempter of the Bone

    The doggie found a bone in an ancient maze, which fascinated him a lot. However, when he picked it up, the maze began to shake, and the doggie could feel the ground sinking. He realized that the bone was a trap, and he tried desperately to get out of this maze.

    The maze was a rectangle with sizes N by M. There was a door in the maze. At the beginning, the door was closed and it would open at the T-th second for a short period of time (less than 1 second). Therefore the doggie had to arrive at the door on exactly the T-th second. In every second, he could move one block to one of the upper, lower, left and right neighboring blocks. Once he entered a block, the ground of this block would start to sink and disappear in the next second. He could not stay at one block for more than one second, nor could he move into a visited block. Can the poor doggie survive? Please help him.


    Input

    The input consists of multiple test cases. The first line of each test case contains three integers N, M, and T (1 < N, M < 7; 0 < T < 50), which denote the sizes of the maze and the time at which the door will open, respectively. The next N lines give the maze layout, with each line containing M characters. A character is one of the following:

    'X': a block of wall, which the doggie cannot enter;
    'S': the start point of the doggie;
    'D': the Door; or
    '.': an empty block.

    The input is terminated with three 0's. This test case is not to be processed.


    Output

    For each test case, print in one line "YES" if the doggie can survive, or "NO" otherwise.


    Sample Input

    4 4 5
    S.X.
    ..X.
    ..XD
    ....
    3 4 5
    S.X.
    ..X.
    ...D
    0 0 0


    Sample Output


    NO
    YES

    题目意思:给定你起点S,和终点D,问你是否能在 T 时刻恰好到达终点D。

    #include<cstring>
    #include<cstdio>
    #include<cmath>
    #include<algorithm>
    using namespace std;
    int map[10][10];
    int a,b,c,d,flag;
    int n,m,t,count;
    int dir[4][2]= {{0,-1},{0,1},{1,0},{-1,0}}; ///分别表示左、右、下、上四个方向
    void DFS(int x,int y,int count)
    {
        int k,p,q,i;
        if(x>n||y>m||x<1||y<1)
        {
            return ;
        }
        if(count==t&&x==c&&y==d)///时间正好才能逃生
        {
            flag=1;
            return ;
        }
        k=(t-count)-(abs(x-c)+abs(y-d))/*当前点到终点的最短路*/;///k为当前点到终点最短路还需要的时间差
        if(k<0||k&1)///k<0或者为奇数则不可能到达
        {
            return ;
        }
        for(i=0; i<4; i++)
        {
            p=x+dir[i][0];
            q=y+dir[i][1];
            if(map[p][q]!='X')
            {
                map[p][q]='X';
                DFS(p,q,count+1);
                if(flag)
                {
                    return ;
                }
                map[p][q]='.';///搜索不到则退出,重新将该点刷成。
            }
        }
        return ;
    }
    int main()
    {
        int w,i,j;///墙的数量
        while(scanf("%d%d%d",&n,&m,&t)!=EOF)
        {
            getchar();
            w=0;
            if(n==0&&m==0&&t==0)
            {
                break;
            }
            for(i=1; i<=n; i++)
            {
                for(j=1; j<=m; j++)
                {
                    scanf("%c",&map[i][j]);
                    if(map[i][j]=='S')///记录狗的位置
                    {
                        a=i;
                        b=j;
                    }
                    else if(map[i][j]=='D')///出口的位置
                    {
                        c=i;
                        d=j;
                    }
                    else if(map[i][j]=='X')///墙的数量
                    {
                        w++;
                    }
                }
                getchar();
            }
            if(n*m-w<=t)///路径剪切,走完了不含墙的迷宫都还不到时间t,迷宫塌陷
            {
                printf("NO
    ");
            }
            else
            {
                flag=0;
                map[a][b]='X';///将狗的起始位置刷为x
                DFS(a,b,0);///这里的DFS函数是一个需要自身调用自身的递归函数,需要设置参数
                if(flag==1)
                {
                    printf("YES
    ");
                }
                else
                {
                    printf("NO
    ");
                }
            }
        }
        return 0;
    }

     

  • 相关阅读:
    EasyNVR RTSP转RTMP-HLS流媒体服务器前端构建之_关于接口调用常见的一些问题(401 Unauthorized)
    EasyNVR H5直播流媒体解决方案前端构建之:如何播放自动适配RTMP/HLS直播播放
    EasyNVR RTSP摄像机转HLS直播服务器中使用Onvif协议控制预置位
    EasyNVR RTSP摄像机HLS直播服务器中使用Onvif协议获取设备快照
    EasyNVR无插件直播服务器如何使用ffmpeg实现摄像机快照功能的
    EasyNVR流媒体服务器接入EasyDSS云视频平台快照上传实现
    EasyDSS RTMP流媒体服务器的HTTP接口query url的C++实现方法
    EasyDSS高性能流媒体服务器前端重构(五)- webpack + vue-router 开发单页面前端实现按需加载
    EasyDSS高性能流媒体服务器前端重构(六)- webpack-dev-server 支持手机端访问
    EasyNVR RTSP转HLS(m3u8+ts)流媒体服务器前端构建之:bootstrap-datepicker日历插件的实时动态展现
  • 原文地址:https://www.cnblogs.com/wkfvawl/p/9337156.html
Copyright © 2020-2023  润新知