剪枝是什么,簡單的說就是把不可行的一些情況剪掉,例如走迷宮時運用回溯法,遇到死胡同時回溯,造成程序運行時間長。剪枝的概念,其實就跟走迷宮避開死胡同差不多。若我們把搜索的過程看成是對一棵樹的遍歷,那么剪枝顧名思義,就是將樹中的一些“死胡同”,不能到達我們需要的解的枝條“剪”掉,以減少搜索的時間。
這里介紹一下奇偶剪枝
什么是奇偶剪枝?
部分內容來自https://blog.csdn.net/chyshnu/article/details/6171758
把矩陣看成如下形式:
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 但是要求時間是偶數的,都可以直接判斷不可達!
比如一張地圖c
- S...
- ....
- ....
- ....
- ...D
要求從S點到達D點,此時,從S到D的最短距離為s = abs ( dx - sx ) + abs ( dy - sy )。
如果地圖中出現了不能經過的障礙物:
- S..X
- XX.X
- ...X
- .XXX
- ...D
此時的最短距離s' = s + 4,為了繞開障礙,不管偏移幾個點,偏移的距離都是最短距離s加上一個偶數距離。
就如同上面說的矩陣,要求你從0走到0,無論你怎么繞,永遠都是最短距離(偶數步)加上某個偶數步;要求你從1走到0,永遠只能是最短距離(奇數步)加上某個偶數步。
例題
Tempter of the Bone
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
題目意思:給定你起點S,和終點D,問你是否能在 T 時刻恰好到達終點D。
#include<cstring> #include<cstdio> #include<cmath> #include<algorithm> using namespace std; int map[10][10]; int a,b,c,d,flag; int n,m,t,count; int dir[4][2]= {{0,-1},{0,1},{1,0},{-1,0}}; ///分別表示左、右、下、上四個方向 void DFS(int x,int y,int count) { int k,p,q,i; if(x>n||y>m||x<1||y<1) { return ; } if(count==t&&x==c&&y==d)///時間正好才能逃生 { flag=1; return ; } k=(t-count)-(abs(x-c)+abs(y-d))/*當前點到終點的最短路*/;///k為當前點到終點最短路還需要的時間差 if(k<0||k&1)///k<0或者為奇數則不可能到達 { return ; } for(i=0; i<4; i++) { p=x+dir[i][0]; q=y+dir[i][1]; if(map[p][q]!='X') { map[p][q]='X'; DFS(p,q,count+1); if(flag) { return ; } map[p][q]='.';///搜索不到則退出,重新將該點刷成。 } } return ; } int main() { int w,i,j;///牆的數量 while(scanf("%d%d%d",&n,&m,&t)!=EOF) { getchar(); w=0; if(n==0&&m==0&&t==0) { break; } for(i=1; i<=n; i++) { for(j=1; j<=m; j++) { scanf("%c",&map[i][j]); if(map[i][j]=='S')///記錄狗的位置 { a=i; b=j; } else if(map[i][j]=='D')///出口的位置 { c=i; d=j; } else if(map[i][j]=='X')///牆的數量 { w++; } } getchar(); } if(n*m-w<=t)///路徑剪切,走完了不含牆的迷宮都還不到時間t,迷宮塌陷 { printf("NO\n"); } else { flag=0; map[a][b]='X';///將狗的起始位置刷為x DFS(a,b,0);///這里的DFS函數是一個需要自身調用自身的遞歸函數,需要設置參數 if(flag==1) { printf("YES\n"); } else { printf("NO\n"); } } } return 0; }