HDU 1010 Tempter of the Bone(DFS+剪枝)

来源:互联网 发布:算法设计与分析基础 3 编辑:程序博客网 时间:2024/06/13 02:22

http://acm.hdu.edu.cn/showproblem.php?pid=1010

大神题解报告http://acm.hdu.edu.cn/forum/read.php?tid=6158

  1. 关于剪枝,没有剪枝的搜索不太可能,这题老刘上课的时候讲过两个剪枝,一个是奇偶剪枝,一个是路径剪枝

  2. 奇偶剪枝:
  3. 把矩阵标记成如下形式:
  4. 0,1,0,1,0
  5. 1,0,1,0,1
  6. 0,1,0,1,0
  7. 1,0,1,0,1
  8. 很明显,如果起点在0 而终点在1 那显然 要经过奇数步才能从起点走到终点,依次类推,奇偶相同的偶数步,奇偶不同的奇数步
  9. 在读入数据的时候就可以判断,并且做剪枝,当然做的时候并不要求把整个矩阵0,1刷一遍,读入的时候起点记为(Si,Sj) 终点记为(Di,Dj) 判断(Si+Sj) 和 (Di+Dj) 的奇偶性就可以了

  10. 路径剪枝:
  11. 矩阵的大小是N*M 墙的数量记为wall 如果能走的路的数量 N*M - wall 小于时间T,就是说走完也不能到总的时间的,这显然是错误的,可以直接跳出了
    #include <cstdlib>#include <cstdio>#include <cstring>#include <queue>#include <cmath>using namespace std;char map[30][30];int vis[30][30];int dx[] = {0, 1, 0, -1};int dy[] = {1, 0, -1, 0};int n, m, t, a, b, flag;struct point{int x, y, step;} st;void dfs(point st);int main(){//freopen("1.txt", "w", stdout);while (~scanf("%d%d%d", &m, &n, &t) && (n + m + t != 0)){int wall = 0;flag = 0;memset(map, 0, sizeof(map));for (int i = 1; i <= m; i++){for (int j = 1; j <= n; j++){scanf(" %c", &map[i][j]);if (map[i][j] == 'S'){memset(vis, 0, sizeof(vis));st.x = i;st.y = j;st.step = 0;}if (map[i][j] == 'D'){a = i;b = j;}if (map[i][j] == 'X'){wall++;}}}dfs(st);if (flag){printf("YES\n");}else{printf("NO\n");}}return 0;}void dfs(point st){int xx = abs(a - st.x), yy = abs(b - st.y), tt = t - st.step;;//printf("x=%d,y=%d,t=%d,%d\n", st.x, st.y, tt, (tt - xx - yy));if(flag == 1){return; //不加这个会TLE}if (tt < 0 || ((tt - xx - yy) % 2 != 0)){return;}else{if (tt == 0){if (map[st.x][st.y] == 'D'){flag = 1;return;}else{return;}}elsefor (int i = 0; i < 4; i++){point next = st;next.x = st.x + dx[i], next.y = st.y + dy[i];int nx = next.x, ny = next.y;if ((map[nx][ny] == '.' || map[nx][ny] == 'D') && nx > 0 && nx <= m && ny > 0 && ny <= n        &&!vis[nx][ny]){next.step++;vis[nx][ny] = 1;dfs(next);vis[nx][ny] = 0;}}}}


0 0
原创粉丝点击