关于剪枝的思考 ——由hdu1010 dfs+剪枝所想到的

来源:互联网 发布:苏州星宇软件 编辑:程序博客网 时间:2024/05/29 16:16

        这道题思路不难,就是剪枝要要求很高,否则老是TLE。

 dfs+剪枝设计思路:

        1,要求的是正好T步到达,不多也不少,所以深度搜索控制的一大条件就是控制步数;

         2,对于剪枝,有这么几个点:

              (1)步数达到T且成功找到Door的,置success为1,同时完成了本题目的要求,结束本次递归 return,并将success是否为1作为本递归函数的结束条件从而达到剪枝的目的;

              (2)步数达到T但没有找到Door的,return;

              (3)提前到达了Door,但步数还没到达T的,return;

              (4)检测本次递归中距离目标的距离为多少步,记为num,然后计算出还有多少步必须要走,记为k,如果num>k,则必然不能到达,return;如果num<k,说明到达目标绰绰有余,还必须绕圈以消耗掉多余的步数,比如下一个格子就可以到目标了,但是因为规定的步数还大于1必须走完,所以不能直接到Door,必须多绕,这样的话会发现,多绕了一个格子,这个格子就不能再走了,再想到达Door就必须再绕两个其他没走过的格子,相比直接到达就多绕了两个格子,所以要求 (num-k) 必须为大于等于2的偶数(这了大家可以亲自试试),如果不是偶数,return ;                       实测发现这是一个很有效的剪枝,可以一举解决TLE的问题,将时间复杂度减小的500ms内。

        关于剪枝,要想真正做好,就得深挖题意,找到那些真正能控制时间的因素,尽力把递归层数控制在一个很小的范围内,这说起来容易做起来难,要么就是多做点此类型的题目,自然能熟能生巧,所谓天道酬勤,就是这个意思吧。

下面是代码:

#include<iostream>#include<cstring>#include<cmath>using namespace std;int a[10][10];char b[10];int flag[4][2]={0,-1,0,1,-1,0,1,0};int startx=0;int starty=0;int endx=0;int endy=0; int M=0,N=0,T=0;int success=0;void dfs(int x,int y,int cnt)//cnt为目前(x,y)当前位子的跳数{if(success==1)return ;   if( cnt==T && x==endx && y==endy)   {     success=1; return ;   }if(x==endx && y==endy){ return;}   if(cnt==T)   {     return ;   }   int num=abs(x-endx)+abs(y-endy);//要到达Door此时至少还要走的步数   int k=T-cnt;   if(num>k || (k-num)%2!=0)//重要剪枝   return;   for(int i=0;i<4;i++)   {   int p1=x+flag[i][0];   int p2=y+flag[i][1];   if(p1<N && p1>=0 && p2<M && p2>=0 && a[p1][p2]!=0)   {       a[p1][p2]=0;   dfs(p1,p2,cnt+1);           a[p1][p2]=1;   }   }   return ;}int main(){ memset(b,'\0',sizeof(b)); memset(a,0,sizeof(a)); while(scanf("%d%d%d",&N,&M,&T)&&( N!=0 && M!=0 && T!=0)) { success=0; int t=N; int i=-1;  while(t--){         i++; scanf("%s",b);//gets(b);不要用gets()       for(int j=0;j<M;j++)   {if(b[j]=='.')       a[i][j]=1;    else if(b[j]=='S'){ a[i][j]=0; startx=i; starty=j;}    else if(b[j]=='D'){   a[i][j]=1;   endx=i;   endy=j;}elsea[i][j]=0;   }memset(b,'\0',sizeof(b));}//输入完毕     dfs(startx,starty,0); if(success)printf("YES\n");elseprintf("NO\n");memset(a,0,sizeof(a)); } return 0;}


0 0
原创粉丝点击