• HDU-1010-Tempter of the Bone


    题目链接

    http://acm.hdu.edu.cn/showproblem.php?pid=1010

    题目意思是讲有一只狗要吃骨头,结果进入了一个迷宫陷阱,迷宫里每走过一个地板费时一秒,该地板 就会在下一秒塌陷,所以你不能在该地板上逗留。迷宫里面有一个门,只能在特定的某一秒才能打开,让狗逃出去。现在题目告诉你迷宫的大小和门打开的时间,问你狗可不可以逃出去,可以就输出YES,否则NO。



    搜索时要用到的剪枝:

    1.如果当前时间即步数(step) >= T 而且还没有找到D点,则剪掉。

    2.设当前位置(x, y)到D点(dx, dy)的最短距离为s,到达当前位置(x, y)已经花费时间(步数)step,那么,如果题目要求的时间T - step < s,则剪掉。

    3. 对于当前位置(x, y),如果,(T-step-s)是奇数,则剪掉(奇偶剪枝)。

    4.如果地图中,可走的点的数目(xnum) < 要求的时间T,则剪掉(路径剪枝)

    #include<stdio.h>

    #include<stdlib.h>

    int n,m,ex,ey,t;

    int success;

    char maze[10][10];

    void dfs(int stx,int sty,int dt)

    {

        if(stx<=0||stx>n||sty<=0||sty>m)

        return ;

        if(stx==ex&&sty==ey&&dt==t)

        {

            success=1;

            return ;

        }

        int temp=(t-dt)-abs(ex-stx)-abs(ey-sty);

        if(temp<0||temp&1)

        return ;

        if(maze[stx][sty+1]!='X')

        {

            maze[stx][sty+1]='X';

            dfs(stx,sty+1,dt+1);

            maze[stx][sty+1]='.';

        }

        if(maze[stx][sty-1]!='X')

        {

            maze[stx][sty-1]='X';

            dfs(stx,sty-1,dt+1);

            maze[stx][sty-1]='.';

        }

        if(maze[stx+1][sty]!='X')

        {

            maze[stx+1][sty]='X';

            dfs(stx+1,sty,dt+1);

            maze[stx+1][sty]='.';

        }

        if(maze[stx-1][sty]!='X')

        {

            maze[stx-1][sty]='X';

            dfs(stx-1,sty,dt+1);

            maze[stx-1][sty]='.';

        }

    }

    int main(void)

    {

        int stx,sty,wall,i,j;

        while(scanf("%d%d%d",&n,&m,&t)==3&&(n+m+t))

        {

            getchar();

            wall=0;

            for(i=1;i<=n;i++)

            {

                for(j=1;j<=m;j++)

                {

                    scanf("%c",&maze[i][j]);

                    if(maze[i][j]=='S')

                    {

                        stx=i;

                        sty=j;

                    }

                    else if(maze[i][j]=='D')

                    {

                        ex=i;

                        ey=j;

                    }

                    else if(maze[i][j]=='X')

                    wall++;

                }

                getchar();

            }

            success=0;

            maze[stx][sty]='X';

            if(n*m-wall<=t)

            printf("NO ");

            else

            {

                dfs(stx,sty,0);

                if(success)

                printf("YES ");

                else

                printf("NO ");

            }

        }

        return 0;

    }

     

    代码

    #include<stdio.h>
    #include<stdlib.h>

    char maze[10][10];
    int success;
    int ex,ey,n,m,t;
    int to[4][2]={{0,1},{0,-1},{1,0},{-1,0}};

    void dfs(int stx,int sty,int dt)
    {
    if(stx==ex&&sty==ey&&dt==t)
    {
    success=1;
    return ;
    }
    int temp=(t-dt)-abs(ex-stx)-abs(ey-sty);
    if(temp<0||temp&1)
    return ;
    int i;
    for(i=0;i<4;i++)
    {
    int x=stx+to[i][0];
    int y=sty+to[i][1];
    if(x>=0&&x<n&&y>=0&&y<m&&maze[x][y]!='X')
    {
    maze[x][y]='X';
    dfs(x,y,dt+1);
    if(success)//不加这里则超时;
    return ;
    maze[x][y]='.';
    }
    }
    return ;
    }

    int main(void)
    {
    int i,j,k;
    int stx,sty;
    while(scanf("%d%d%d",&n,&m,&t)==3&&(n+m+t))
    {
    k=0;
    getchar();
    for(i=0;i<n;i++)
    {
    for(j=0;j<m;j++)
    {
    scanf("%c",&maze[i][j]);
    if(maze[i][j]=='S')
    {
    stx=i;
    sty=j;
    }
    else if(maze[i][j]=='D')
    {
    ex=i;
    ey=j;
    }
    else if(maze[i][j]=='X')
    {
    k++;
    }
    }
    getchar();
    }
    success=0;
    maze[stx][sty]='X';
    if(n*m-k-1<t)
    {
    printf("NO ");
    continue;
    }
    dfs(stx,sty,0);
    if(success)
    printf("YES ");
    else
    printf("NO ");
    }
    return 0;
    }



     

    什么是奇偶剪枝?

    把矩阵看成如下形式: 
    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-sharp] view plaincopy
     
    1. S...  
    2. ....  
    3. ....  
    4. ....  
    5. ...D  

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

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

    [c-sharp] view plaincopy
     
    1. S..X  
    2. XX.X  
    3. ...X  
    4. .XXX  
    5. ...D  

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

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

     

     

    同时可以搜 奇偶剪枝。 

  • 相关阅读:
    [HEOI2013]Eden 的新背包问题
    [UOJ#77]A+B Problem
    [CodeForces]786B Legacy
    [LUOGU]P4098[HEOI2013]ALO
    [BZOJ3207]花神的嘲讽计划
    [LUOGU]P2633 Count on a tree
    【东莞市选2007】拦截导弹
    [JZOJ] 3462. 【NOIP2013模拟联考5】休息(rest)
    [BZOJ] 2705: [SDOI2012]Longge的问题
    [BZOJ] 1191: [HNOI2006]超级英雄Hero
  • 原文地址:https://www.cnblogs.com/liudehao/p/4005813.html
Copyright © 2020-2023  润新知