剪枝的定义&&hdu1010

半年前在POJ上遇到过一次剪枝的题目,那时觉得剪枝好神秘。。。今天在网上查了半天资料,终于还是摸索到了一点知识,但是相关资料并不多,在我看来,剪枝是技巧,而不是方法,也就是说,可能一点实用的小技巧,让程序可以少判断一点,这就是剪枝,剪枝无处不在,

搜索的进程可以看作是从树根出发,遍历一棵倒置的树—-搜索树的过程。而所谓的剪枝,顾名思义,就是通过某种判断,避免一些不必要的遍历过程,形象的说,就是减去了搜索树中的某些“枝条”,故称剪枝。
(杭电课件上是这么说的:即剪去解答树上已被证明不可能存在可行解或最优解的子树.)

既 然采用了搜索,剪枝就显得十分的必要,即使就简简单单的设一个槛值,或多加一两条判断,就可对搜索的效率产生惊人的影响。例如N后问题,假如放完皇后再判 断,则仅仅只算到7,就开始有停顿,到了8就已经超过了20秒,而如果边放边判断,就算到了10,也没有停顿的感觉。所以,用搜索一般都就要剪枝。

剪枝至少有两方面,一是从方法上剪枝,如采用分枝定界,启发式搜索等,适用范围比较广;二是使用一些小技巧,这类方法适用性虽不如第一类,有时甚至只能适用一道题,但也十分有效,并且几乎每道题都存在一些这样那样的剪枝技巧,只是每题有所不同而已。

剪枝的原则:
1.正确性:必须保证不丢失正确的结果。
2.准确性:能够尽可能多的减去不能通向正解的枝条
3.高效性:在很多时候,为了加强优化的效果,我们会增加一些判断,这样对程序效率也带来了副作用,所以要考虑剪枝的高效性,否则得不偿失。

最后说一下:剪枝在搜索中用的是非常的广泛的。

参照杭电课件第47页一句话:
ACMer们:
为了ACM事业,努力地剪枝吧!!


题目我不多说,HDOJ 1010就是一个很好的剪枝题目。

另外,杭电的课件–搜索篇里面也讲了搜索与剪枝。

 

Tempter of the Bone

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 91553    Accepted Submission(s): 24900


Problem Description

 

The doggie found a bone in an ancient maze, which fascinated him a lot. However, when he picked it up, the maze began to shake, and the doggie could feel the ground sinking. He realized that the bone was a trap, and he tried desperately to get out of this maze.

The maze was a rectangle with sizes N by M. There was a door in the maze. At the beginning, the door was closed and it would open at the T-th second for a short period of time (less than 1 second). Therefore the doggie had to arrive at the door on exactly the T-th second. In every second, he could move one block to one of the upper, lower, left and right neighboring blocks. Once he entered a block, the ground of this block would start to sink and disappear in the next second. He could not stay at one block for more than one second, nor could he move into a visited block. Can the poor doggie survive? Please help him.

 

 


Input

 

The input consists of multiple test cases. The first line of each test case contains three integers N, M, and T (1 < N, M < 7; 0 < T < 50), which denote the sizes of the maze and the time at which the door will open, respectively. The next N lines give the maze layout, with each line containing M characters. A character is one of the following:

'X': a block of wall, which the doggie cannot enter;
'S': the start point of the doggie;
'D': the Door; or
'.': an empty block.

The input is terminated with three 0's. This test case is not to be processed.

 

 


Output

 

For each test case, print in one line "YES" if the doggie can survive, or "NO" otherwise.

 

 


Sample Input

 

4 4 5 S.X. ..X. ..XD .... 3 4 5 S.X. ..X. ...D 0 0 0

 

 


Sample Output

 

NO YES

 

 


Author

 

ZHANG, Zheng

 

 


Source

 

 

 


Recommend

 

JGShining   |   We have carefully selected several similar problems for you:  1016 1242 1072 1026 1240 

 

 
#include<iostream>
#include<math.h>
using namespace std;
char s[10][10];
int ax,ay,bx,by,n,m,k;
int t[4][2]={1,0,-1,0,0,1,0,-1},vist[10][10],flag;

void dfs(int x,int y,int count){
    int i,mx,my;
    if(x==bx&&y==by){
        if(k==count)
            flag=1;
        return;
    }
    if(count>=k)
        return;
    if(s[x][y]!='X'){
        for(i=0;i<4;i++){
            mx=x+t[i][0];
            my=y+t[i][1];
            if(s[mx][my]!='X'&&mx>=1&&mx<=n&&my>=1&&my<=m&&!vist[mx][my]){
                vist[mx][my]=1;
                dfs(mx,my,count+1);
                vist[mx][my]=0;
                if(flag)                       //注意,在找到了目标之后,就不需要再找!以往编写dfs时,没有注意这点
                    return;
            }
        }
    }
}
int main(){
    while(scanf("%d%d%d",&n,&m,&k)>0&&(n+m+k)){
        int i,count;
        for(i=1;i<=n;i++){
            getchar();
            for(int j=1;j<=m;j++){
                scanf("%c",&s[i][j]);
                if(s[i][j]=='S'){
                    ax=i;
                    ay=j;
               }
                if(s[i][j]=='D'){
                    bx=i;
                    by=j;
               }
            }
        }
        getchar();
        memset(vist,0,sizeof(vist));
        if(abs(ax-bx)+abs(ay-by)>k||(ax+bx+ay+by+k)%2==1){//剪枝
            printf("NO\n");
            continue;
        }
        vist[ax][ay]=1;
        flag=0;
        count=0;
        dfs(ax,ay,count);
        if(flag==1)
            printf("YES\n");
        else
            printf("NO\n");
    }
    return 0;
}

 

 

posted @ 2015-09-10 20:25  柳下_MBX  阅读(414)  评论(0编辑  收藏  举报