梦,才是最真的现实

导航

HDU 1010第一道剪枝的DFS

自己写果断超时了,看了大神的剪枝,果然好强悍,附上剪枝

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

解题思路:这道题,要用到剪枝搜索来做,否则会超时。剪掉的条件是,如果可走地板数目小于给定的时间,绝对不可能得救。还有就是狗走到门的时间必须和题目给定的时间是同奇同偶的,否则也不能在指定的那秒到达门,也不可能得救,剪掉这两种情况后。就用深度搜索来做。从起点出发,深搜周围的路,走过的路就标记为不可走,一直搜索下去,如果搜索失败就回溯,恢复原数据,把可能的路都搜索一遍过去,看看是否有可行方案。

关于剪枝,没有剪枝的搜索不太可能,一个是奇偶剪枝,一个是路径剪枝

奇偶剪枝:
把矩阵标记成如下形式:
0,1,0,1,0
1,0,1,0,1
0,1,0,1,0
1,0,1,0,1
很明显,如果起点在0 而终点在1 那显然 要经过奇数步才能从起点走到终点,依次类推,奇偶相同的偶数步,奇偶不同的奇数步
在读入数据的时候就可以判断,并且做剪枝,当然做的时候并不要求把整个矩阵0,1刷一遍,读入的时候起点记为(Si,Sj) 终点记为(Di,Dj) 判断(Si+Sj) 和 (Di+Dj) 的奇偶性就可以了

路径剪枝:
矩阵的大小是N*M 墙的数量记为num 如果能走的路的数量 N*M - num 小于时间T,就是说走完也不能到总的时间的,这显然是错误的,可以直接跳出了

剪枝3:就是记录当前点到终点的最短路,如果小于剩余的时间的话,就跳出


#include<stdio.h>
#include<math.h>
#include<string.h>
typedef struct 
{
    int x;
    int y;
}position;
position exit,move[4]={-1,0,0,1,1,0,0,-1};
char maze[10][10];
int visited[10][10],t,sum;
bool found;
void dfs(position,int );
void wall(int r,int c);
void findenter(position &,position&,int ,int );
int main()
{
    position enter;
    int r,c,i;
    while(scanf("%d %d %d",&r,&c,&t)&&r+c+t)
    {
        sum=0;
        found=false;
        memset(visited,0,sizeof(visited));
        for(i=1;i<=r;i++)
            scanf("%s",&maze[i][1]);
        wall(r,c);
        findenter(enter,exit,r,c);
        if(sum+1<t) 
        {
            printf("NO\n");
            continue;
        }
        dfs(enter,0);
        if(found) printf("YES\n");
        else printf("NO\n");
    }
    return 0;
}
void wall(int r,int c)
{
    int i;
    for(i=0;i<=r+1;i++)
    {
        maze[i][0]='X';
        maze[i][c+1]='X';
    }
    for(i=0;i<=c+1;i++)
    {
        maze[0][i]='X';
        maze[r+1][i]='X';
    }
}
void findenter(position &enter,position &exit,int r,int c)
{
    int i,j;
    for(i=1;i<=r;i++)
        for(j=1;j<=c;j++)
        {
            if(maze[i][j]=='.')
                sum++;
            else if(maze[i][j]=='S')
            {
                enter.x=i;
                enter.y=j;
            }
            else if(maze[i][j]=='D')
            {
                exit.x=i;
                exit.y=j;
            }
        }
}
void dfs(position now,int step)
{
    int i,temp;
    position next;
    if(found) return ;
    if(maze[now.x][now.y]=='D'&&step==t)
    {
        found=true;
        return;
    }
    temp=t-step-abs(now.x-exit.x)-abs(now.y-exit.y);
    if(temp<0||temp%2) return ;
    visited[now.x][now.y]=1;
    for(i=0;i<4;i++)
    {
        next.x=now.x+move[i].x;
        next.y=now.y+move[i].y;
        if(!visited[next.x][next.y]&&maze[next.x][next.y]!='X')
        {
            visited[next.x][next.y]=1;
            dfs(next,step+1);
            visited[next.x][next.y]=0;
        }
    }
}


posted on 2012-05-27 00:54  梦,才是最真的现实  阅读(171)  评论(0编辑  收藏  举报