题目大意:给定你起点S,和终点D,X为墙不可走,问你是否能在 T 时刻恰好到达终点D。
参考: 奇偶剪枝
奇偶剪枝简单解释:
在一个只能往X、Y方向走的方格上,从起点到终点的最短步数为T1,并记其他任意走法所需步数为T2,则T2-T1一定为偶数。
即若某一点到终点的最短步数为T1,且T3-T1为奇数,则一定无法话费T3步恰好到达终点。
/*HDU 1010 ------ Tempter of the Bone DFS*/ #include <cstdio> #include <cstring> int m, n, t, startx, starty, endx, endy; char mapp[10][10]; bool visit[10][10], ans, flag; /*求a-b的绝对值*/ int abs(int a, int b){ if (a < b) return b - a; else return a - b; } /*搜索从i,j处走走到出口的结果 i j为横纵坐标 c为当前已走步数*/ void DFS(int i, int j, int c){ if (flag || c > t || i <= 0 || i > n || j <= 0 || j > m) return; if (mapp[i][j] == 'D' && c == t){ ans = flag = 1; return; } int tmp = abs(i, endx) + abs(j, endy); //最短可到距离 tmp = t - c - tmp; //t-c为剩余可走步数 减去最短距离为 剪纸 if (tmp & 1) //若剪枝后tmp为奇数 一定不可到达 return; //左边的点可以访问 if (!visit[i - 1][j] && mapp[i - 1][j] != 'X'){ visit[i - 1][j] = true; DFS(i - 1, j, c + 1); visit[i - 1][j] = false; } //右边的点可以访问 if (!visit[i + 1][j] && mapp[i + 1][j] != 'X'){ visit[i + 1][j] = true; DFS(i + 1, j, c + 1); visit[i + 1][j] = false; } //上边的点可以访问 if (!visit[i][j - 1] && mapp[i][j - 1] != 'X'){ visit[i][j - 1] = true; DFS(i, j - 1, c + 1); visit[i][j - 1] = false; } //下边的点可以访问 if (!visit[i][j + 1] && mapp[i][j + 1] != 'X'){ visit[i][j + 1] = true; DFS(i, j + 1, c + 1); visit[i][j + 1] = false; } } int main() { //n行m列t步 while (scanf("%d%d%d", &n, &m, &t) == 3 && (m + n + t)){ int k = 0; memset(visit, 0, sizeof visit); //i,j取1是为了判别时数组不越界 for (int i = 1; i <= n; ++i){ scanf("%s", mapp[i]+1); for (int j = 1; j <= m; ++j){ if (mapp[i][j] == 'X'){ ++k; //记录墙的数量 } else if (mapp[i][j] == 'S'){ startx = i; //记录起始点 starty = j; visit[i][j] = true; } else if (mapp[i][j] == 'D'){ endx = i; //记录终点 endy = j; } }//for(j) }//for(i) ans = flag = 0; if (n*m - k - 1 >= t) //总数-墙-起点 需大于等于 步数 DFS(startx, starty, 0); if (ans) printf("YES "); else printf("NO "); } return 0; }