题目一直说的是时间,因为一秒一步,实际上就是在找到出口时是否走了恰好走了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;
}