hdu 1010 Tempter of the Bone

  这题是深搜的典型题,要在时间 t 内准确到达终点,处理不好要么 wa 要么 TLE。有两个很重要的剪枝:一是奇偶剪枝,必须提前判断好 'S'和'D' 之间的曼哈顿距离和时间 t 是否同奇偶,否则会 TLE;二是判断 '.' 的数量是否大于或等于 t-1,这个能使程序快很多,但不是必要的,我试了下把它去掉后还是能过,只是多了几倍的时间。

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 using namespace std;
 5 typedef const int& cintr;
 6 int n,m,t,ei,ej;
 7 
 8 inline int dist(cintr x, cintr y, cintr x2, cintr y2){
 9     return abs(x-x2)+abs(y-y2);
10 }
11 
12 bool flag;
13 char map[10][10];
14 int dir[2][4]= {{-1,0,0,1},{0,-1,1,0}};
15 
16 void dfs(int i, int j, int time){
17     if(flag)    return ;
18     if(i==ei && j==ej && time==t) {
19         flag= true;
20         return ;
21     }
22     int tmp= dist(i,j,ei,ej);
23     //不用再作奇偶剪枝的判断了,在主函数时已判断好,这里只需作时间的判断 
24     if(time+tmp > t /*|| (tmp+t-time)&1*/)    return ;
25     for(int k=0; k<4; ++k){
26         cintr di= i+dir[0][k],    dj= j+dir[1][k];
27         char ch= map[di][dj];
28         if(map[di][dj]!='X'){
29             map[di][dj]= 'X';
30             dfs(di,dj,time+1);
31             map[di][dj]= ch;
32         }
33     }
34 }
35 
36 int main(){
37     int i,j,si,sj;
38     while(~scanf("%d%d%d",&n,&m,&t),n){
39         memset(map,'X',sizeof(map));
40         flag= false;
41         int point= 0;
42         getchar();
43         for(i=1; i<=n; ++i,getchar())
44             for(j=1; j<=m; ++j)
45                 if((map[i][j]= getchar())=='S')    si= i,    sj= j;
46                 else if(map[i][j]=='D')    ei= i,    ej= j;
47                 else if(map[i][j]=='.')      ++point;
48         int tmp= dist(si,sj,ei,ej);
49         //两个很重要的剪枝,用point来作首要的判断(大大提高了效率),
50         //然后是奇偶剪枝,只需剪一次即可
51         if(point < t-1 || (tmp+t)&1) {
52             puts("NO");
53             continue;
54         }
55         map[si][sj]= 'X';
56         dfs(si,sj,0);
57         puts(flag? "YES":"NO");
58     }
59     return 0;
60 }

  后来想用 bfs 来做时发觉这题是不能用 bfs 的,因为 bfs 把后继结点都标记好后无法回退。

原文地址:https://www.cnblogs.com/Newdawn/p/4394026.html