奇偶剪枝算法
剪枝是什么,简单的说就是把不可行的一些情况剪掉,例如走迷宫时运用回溯法,遇到死胡同时回溯,造成程序运行时间长。
剪枝的概念,其实就跟走迷宫避开死胡同差不多。若我们把搜索的过程看成是对一棵树的遍历,那么剪枝顾名思义,就是将树中的一些“死胡同”,不能到达我们需要的解的枝条“剪”掉,以减少搜索的时间。
剪枝种类较多,说一下奇偶剪枝
把矩阵看成如下形式:
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 但是要求时间是偶数的,都可以直接判断不可达!
例题:HDU 1010
http://acm.hdu.edu.cn/showproblem.php?pid=1010
1 #include <cstdio> 2 #include <cmath> 3 #include <iostream> 4 using namespace std; 5 char mat[6][6]; 6 bool flg,visit[6][6]; 7 const int dir[4][2] = {{1,0},{0,1},{-1,0},{0,-1}}; 8 int n,m,t,xnum,sx,sy,ex,ey; 9 void dfs(int x, int y, int step) { 10 if(flg) return; 11 if(step == t && x == ex && y == ey) { 12 flg=true; 13 return; 14 } 15 if(step >= t) return; 16 int dis = abs((double)x-ex) + abs((double)y-ey); 17 dis = t-dis-step; 18 if(dis<0 || dis%2) return;//奇偶剪枝 19 for( int i=0; i<4; ++i) { 20 int tx = x+dir[i][0]; 21 int ty = y+dir[i][1]; 22 int tstep = step+1; 23 if(tx>=0 &&tx<n &&ty>=0 &&ty<m &&!visit[tx][ty] &&mat[tx][ty] != 'X') { 24 visit[tx][ty] = true; 25 dfs(tx,ty,tstep); 26 visit[tx][ty] = false;//回溯 27 } 28 } 29 return; 30 } 31 32 int main() { 33 freopen("C:\\CODE\\in.txt", "r", stdin); 34 while(~scanf("%d%d%d",&n,&m,&t)&&n+m+t) { 35 //printf("n=%d m=%d t=%d\n",n,m,t); 36 37 xnum = 0; 38 flg = false; 39 for( int i=0; i<n; ++i) { 40 getchar(); 41 for( int j=0; j<m; ++j) { 42 visit[i][j]=false; 43 scanf("%c",&mat[i][j]); 44 if('S' == mat[i][j]) { 45 sx=i; 46 sy=j; 47 visit[i][j]=true; 48 } else if('D' == mat[i][j]) { 49 ex=i; 50 ey=j; 51 } else if('X' == mat[i][j]) { 52 ++xnum; 53 } 54 } 55 } 56 getchar(); 57 58 if(n*m-xnum > t) 59 dfs(sx,sy,0); 60 if(flg) 61 puts("YES"); 62 else 63 puts("NO"); 64 } 65 fclose(stdin); 66 return 0; 67 }
----------------
人们生成的最美好的岁月其实就是最痛苦的时候,只是事后回忆起来的时候才那么幸福。