dfs剪枝1

来源:互联网 发布:淘宝如何增加访客 编辑:程序博客网 时间:2024/05/22 13:41

hud1010题Tempter of the Bone
题目链接;http://acm.hdu.edu.cn/showproblem.php?pid=1010
题目意思就是问t时刻是否可以从S到达D处;其中有w墙的阻碍。
一道剪枝题;先了解一下奇偶剪枝和路径剪枝;
就该题而言;

奇偶剪枝的;(剩余步数(最短的)与剩余的时间同奇偶)
原理;在矩阵中当初末位置确定后,那么它从初到末的步数的奇偶也就确定了。(因为每弯一次都是增加2步,不改变奇偶性的);
初末位置的最短路径(不走对角)
abs(ex-sx)+abs(ey-sy);
动态的最短路径是; abs(ex-x)+abs(ey-y);
再结合剩余的时间;就可以得出;
剩余的时间也要与剩余的最短路径同奇偶才能实现在t时刻到达D处;

team=abs(t-cen)-(abs(ex-x)+abs(ey-y));//剩余的时间也要与剩余的最短路径同奇偶if(temp%2==1)return;//意思就是这条路径不行,返回上一级;

路径剪枝;
1’;在最开始的时候可以判断‘可以走的格子个数小于时间则不能到达’;
2’;剩余的最短路径要小于剩余的时间;否则不能到达;

team=abs(t-cen)-(abs(ex-x)+abs(ey-y));//剩余的时间减去剩余的最短路径;if(team<0)return ;//意思就是这条路径不行,返回上一级;

两者结合起来就是;

team=abs(t-cen)-(abs(ex-x)+abs(ey-y));//剩余的时间减去剩余的最短路径;if(team<0||temp%2==1)return ;//意思就是这条路径不行,返回上一级;

这题目除了剪枝外还有一个小知识;就是回溯;
每次完成一次搜索之后又要把其还原为’.’;
代码;

if(fx>=0&&fx<n&&fy>=0&&fy<m&&map[fx][fy]!='X')        {            map[fx][fy]='X';//变化;这个步骤就是实现搜索的中心             dfs(fx,fy,cnt+1);            map[fx][fy]='.'; //回溯        }

也正是他们两者的转化才实现了,搜索;
题目代码;

#include<stdio.h>#include<stdlib.h>#include<math.h> int m,n,t;char map[8][8];int dir[4][2]={{1,0},{-1,0},{0,-1},{0,1}};int ex,ey,sx,sy,k;//e表示end,终点,s表示start,出发点,ok用来判断是否在规定时间到达void dfs(int x,int y,int cnt){    int i;    if(cnt==t)//剪枝1:到时间了符合条件ok=1再退出,不符合条件直接退出。    {        if(ex==x&&ey==y)k=1;        return;    }    if(k)   return;//找到解后还有部分在继续搜索,这条是为了让其它搜索停止;    //动态判断,路径与时间的奇偶性;      int temp=abs(cnt-t)-(abs(x-ex)+abs(y-ey));//剪枝2:((((要点))))    //奇偶性剪枝 ,起点和终点确定以后就可以确定走的步数是奇数还是偶数,通过这个特点来剪枝    if(temp<0||temp%2==1)return;    for(i=0;i<4;i++)    {        int fx=x+dir[i][0];        int fy=y+dir[i][1];        if(fx>=0&&fx<n&&fy>=0&&fy<m&&map[fx][fy]!='X')        {            map[fx][fy]='X';//变化;这个步骤就是实现搜索的中心             dfs(fx,fy,cnt+1);            map[fx][fy]='.'; //回溯        }    }    return ; }int main(){    int i,j,wall;     while(scanf("%d %d %d",&n, &m, &t) != EOF){        wall=0;        if(n==0&&m==0&&t==0)            break;        for(i = 0; i < n; i++){            scanf("%s",map[i]);            for(j=0;map[i][j]!='\0';j++){                if(map[i][j]=='S'){                    sx=i;sy=j;                }                else if(map[i][j]=='D'){                    ex=i;ey=j;                }                else if(map[i][j]=='X')                    wall++;            }        }           if(m*n-wall<=t) printf("NO\n");//剪枝3:能走的格子个数比时间少的话,直接不符合,不用再搜了        else        {            k=0;            map[sx][sy]='X';            dfs(sx,sy,0);            if(k)printf("YES\n");            else printf("NO\n");        }    }    return 0 ;}
1 0
原创粉丝点击