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\n");

        else

        {

            dfs(stx,sty,0);

            if(success)

            printf("YES\n");

            else

            printf("NO\n");

        }

    }

    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\n");
continue;
}
dfs(stx,sty,0);
if(success)
printf("YES\n");
else
printf("NO\n");
}
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,永远只能是最短距离(奇数步)加上某个偶数步。

 

 

同时可以搜 奇偶剪枝。 

 

posted @ 2014-10-04 11:56  立刻行动  阅读(151)  评论(0编辑  收藏  举报