zoj 2110 Tempter of the Bone ——DFS+剪枝

题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=1110

题意:

  给一个矩阵,‘X’代表墙壁,‘.’代表空格,‘S’代表起始位置,‘D’代表终点。从起点开始,每个空格只许经过一次,求在规定的时间t的时候,能否正好到达终点。每走一个花费1个单位时间。输入n,m,t,分别代表矩阵的行,列,规定的时间。

思路:

  深度优先搜索,从起点开始,按照四个方向搜索,判断某个方向的下一个方格如果不是墙壁的话,就把它标为墙壁,然后从这个点继续往下搜索,如果从这个点往下搜索失败后,就要把这个点标记回原来的空格符号:‘.’。然后尝试下一个方向。直到i == di, j == dj, t == T的时候,表示搜索成功,flag = true; return; 其中si sj 是起点位置,di dj是终点位置,T是当前所花费的时间。

  然后还有几处剪枝:如果这个矩阵的空格的数目小于等于时间t,那么不可能成功。这在主函数里面可以剪枝。在dfs的过程中,如果发现剩余的时间小于当前位置到终点的最小距离,可以直接判断搜索失败;如果剩余的时间和当前位置到终点的最小时间的差值是奇数的话,可以判断搜索一定失败,可以剪枝,如果是偶数的话,则可能成功。

  今天突然发现,以前写的解题报告太搓了……向kedebug的博客学习,O(∩_∩)O哈哈~加油

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstdlib>
 4 #include <cstring>
 5 #include <cctype>
 6 #include <stack>
 7 #include <queue>
 8 #include <cmath>
 9 #include <algorithm>
10 #define lson l, m, rt<<1
11 #define rson m+1, r, rt<<1|1
12 using namespace std;
13 typedef long long int LL;
14 const int MAXN =  0x3f3f3f3f;
15 const int  MIN =  -0x3f3f3f3f;
16 const double eps = 1e-9;
17 
18 bool flag;
19 char s[9][9];
20 int t, n, m, si, sj, di, dj;
21 int dir[4][4] = {{0, 1}, {1, 0}, {-1, 0}, {0, -1}};
22 void dfs(int i, int j, int T){
23   if (i == di && j == dj && T == t){
24     flag = true; return;
25   }
26   if (i <= 0 || j <= 0 || i > n || j > m) return;
27   int temp = t - T - abs(i-di) - abs(j-dj);
28   if (temp < 0 || temp&1)return;
29   for (int k = 0; k < 4; ++k){
30     if (s[i+dir[k][0]][j+dir[k][1]] != 'X'){
31       s[i+dir[k][0]][j+dir[k][1]] = 'X';
32       dfs(i+dir[k][0], j+dir[k][1], T+1);
33       if (flag) return;
34       s[i+dir[k][0]][j+dir[k][1]] = '.';
35     }
36   }
37   return;
38 }
39 int main(void){
40 #ifndef ONLINE_JUDGE
41   freopen("zoj2110.in", "r", stdin);
42 #endif
43   while (~scanf("%d%d%d", &n, &m, &t) && m+n+t){
44     getchar();
45     int wall = 0;
46     for (int i = 1; i <= n; ++i){
47       for (int j = 1; j <= m; ++j){
48         scanf("%c", &s[i][j]);
49         if (s[i][j] == 'S'){
50           si = i; sj = j;
51         }
52         else if (s[i][j] == 'D'){
53           di = i; dj = j;
54         }
55         else if (s[i][j] == 'X') wall++;
56       }
57       getchar();
58     }
59     if (m * n - wall <= t){
60       printf("NO\n"); continue;
61     }
62     flag = false;
63     s[si][sj] = 'X';
64     dfs(si, sj, 0);
65     if (flag) printf("YES\n");
66     else printf("NO\n");
67   }
68 
69   return 0;
70 }

开始敲的有错误,怎么也找不出来,然后急了,重新写了一遍,对了……代码能力,准确度有木有!!

还有一点,就是这种读字符的题目,并且是一个一个字符读的,每行要用一个getchar()吸收换行符。并且读字符之前也要用一个getchar()吸收之前读数字的换行符,这个地方特别容易出错。

原文地址:https://www.cnblogs.com/liuxueyang/p/3003192.html