题目一直说的是时间,因为一秒一步,实际上就是在找到出口时是否走了恰好走了T步,注意此时走的路径不一定是最短路径,有可能饶了几步才刚好T步到达终点
简单的DFS,标准的迷宫求解型的题目,输入时用变量记录下开始的坐标,终点的坐标。
对于开始站的位置在刚开始就要记录一下,因为在深搜过程中开始站的地方已经不能走了。
利用一个flag在递归过程中进行简单的剪枝,因为在找到正确答案后就不需要再增加递归深度了。
注意标记与回溯,边界判断,以及边界和标记的判断顺序,防止数组越界访问
#include <stdio.h> #include <string.h> #include <stdlib.h> char a[10][10]; int vis[10][10]; int sizev = sizeof(vis); int flag; int s_i, s_j, d_i, d_j; int M, N, T; void f(int i, int j, int dep) { if (i == d_i && j == d_j) { ///递归出口 if (T == dep) { flag = 1; ///当找到door的坐标,并且dep和要求的时间相等时,找到出口,标记flag以后不再增加递归深度 } return ; } ///对于当前位置的上下左右进行DFS ///注意&&的先后顺序和短路效应 ///写成!flag && !vis[i - 1][j] && i - 1 >= 0会因为vis在i - 1 < 0时越界访问而出错,i + 1, j - 1, j + 1同样注意越界问题 if (!flag && i - 1 >= 0 && !vis[i - 1][j]) { vis[i - 1][j] = 1; ///标记表示已经走过 f(i - 1, j, dep + 1); vis[i - 1][j] = 0; ///回溯,删除标记,为其他可能路径留出空间 } if (!flag && j + 1 < M && !vis[i][j + 1]) { vis[i][j + 1] = 1; f(i, j + 1, dep + 1); vis[i][j + 1] = 0; } if (!flag && i + 1 < N && !vis[i + 1][j]) { vis[i + 1][j] = 1; f(i + 1, j, dep + 1); vis[i + 1][j] = 0; } if (!flag && j - 1 >= 0 && !vis[i][j - 1]) { vis[i][j - 1] = 1; f(i, j - 1, dep + 1); vis[i][j - 1] = 0; } } int main() { #if 0 freopen("data.in", "r", stdin); freopen("data.out", "w", stdout); #endif // 1 int i, j; while (~scanf("%d%d%d", &N, &M, &T)) { getchar(); ///留意缓冲 if (N == 0 && M == 0 && T == 0) break; memset(vis, 0, sizev); ///初始化标记路径数组 for (i = 0; i < N; i++) { for (j = 0; j < M; j++) { scanf("%c", &a[i][j]); if (a[i][j] == 'S') { s_i = i; s_j = j; vis[i][j] = 1; ///对于起点,开始的时候就要赋值1 } if (a[i][j] == 'X') vis[i][j] = 1; ///墙不能走 if (a[i][j] == 'D') { d_i = i; d_j = j; ///记录出口位置 } } getchar(); ///留意缓冲 } flag = 0; ///初始化flag f(s_i, s_j, 0); ///从起点开始,起点走的步数为0 if (flag) printf("YES"); else printf("NO"); puts(""); } return 0; }