题目链接:Click here~~
今天下午做了这道深搜题,弄了半天,终于对深搜有了初步的认识。
题目大意就是给你一个迷宫,要你判断有没有一条路径,可以在时间t时恰好到达终点。
搜索的魅力,无疑在于剪枝。对于这道题,可以有4种剪枝。
1.如果当前搜索的深度(时间)大于时间t,中止搜索。
2.如果已经搜索到结果,中止搜索。
3.如果当前所剩余的时间小于从当前位置到终点的理论最短时间,必定不能到达,中止搜索。
4.传说中的奇偶性剪枝,详细介绍如下:
我们把map看成这样:
/* 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步,不管哪个方向,都会走到1的格子上。
于是我们得出这样的结论:
0->1 或 1->0 必定走奇数步,
0->0 或 1->1 必定走偶数步。
所以当我们遇到不满足上述两个结论的,可以推断它不能到达,所以中止搜索。
还有一种特殊情况,就是当地图上能走的点的个数(不包括起点)小于时间t的时候,显然不能到达,这时可以不用搜索,直接输出NO;
#include <stdio.h> #include <string.h> #include <stdlib.h> //gcc中abs()在stdlib.h里 int ko,fr_x,fr_y,to_x,to_y; bool map[9][9]; int dir[]={0,1,0,-1,1,0,-1,0}; bool find; void dfs(int x,int y,int step) { if(find == true || step >= ko) //剪枝1、2 return ; /* if(ko-step < abs(x-to_x) + abs(y-to_y)) //剪枝3 return ; if( (ko-step)%2 != (abs(x-to_x) + abs(y-to_y))%2 )//剪枝4 return ; */ int cut = ko-step-abs(x-to_x)-abs(y-to_y); if(cut<0 || cut&1) //剪枝3、4 return ; for(int k=0;k<8;) { int _x = x + dir[k++]; int _y = y + dir[k++]; if(_x == to_x && _y == to_y && step+1 == ko) { find = true; return ; } if(map[_x][_y] == 1) { map[_x][_y]=0; dfs(_x,_y,step+1); map[_x][_y]=1; //精华 } } } int main() { int h,w; while(scanf("%d%d%d",&h,&w,&ko),h) { memset(map,0,sizeof(map)); getchar(); int cnt=0; for(int i=1;i<=h;i++) { for(int j=1;j<=w;j++) { char c = getchar(); switch(c) { case 'X':cnt++;break; case 'S':fr_x=i,fr_y=j;break; case 'D':to_x=i;to_y=j;break; case '.':map[i][j]=1;break; } } getchar(); } if(h*w-cnt <= ko) //特殊情况 { puts("NO"); continue; } find = false; dfs(fr_x,fr_y,0); if(find) puts("YES"); else puts("NO"); } return 0; }