题目
暑假的时候,小明和朋友去迷宫中寻宝。然而,当他拿到宝贝时,迷宫开始剧烈震动,他感到地面正在下沉,他们意识到这是一个陷阱!他们想尽一切办法逃出去。 迷宫是一个大小为 N*M 的长方形,迷宫中有一扇门。一开始,门是关着的,他会在第 t 秒的时间打开。因为,小明和朋友必须在第 t 秒到大门口。每一秒,他都可以向上下左右四个方向移动一个点。一旦他移动了,他刚才所在的点就消失,(这意味着他不能回到他已经走过的点)。他不能在一个点上停留超过一秒,并且不能走障碍点。小明和朋友能安全的逃出吗?
Input
输入由多个测试用例组成。每个测试用例的第一行包含三个整数 N、M 和 T ( 1 < N , M < 7 ; 0 < T < 50 ),分别表示迷宫的大小和门打开的时间。接下来的N行给出迷宫布局,每一行包含M个字符。下列字母分别表示: “X”: 一堵墙,小明和朋友不能在上面停留 “S”: 起点 “D”: 门 “.”: 可以走的点
Output
对于每组样例输出一行。 如果小明能够安全逃出,输出 “YES” ,否则输出 “NO”。
样例
样例输入
4 4 5
S.X.
..X.
..XD
....
3 4 5
S.X.
..X.
...D
0 0 0
样例输出
NO
YES
AC代码
#include <iostream>
#include <cstring>
#include <cmath>
using namespace std;
int n, m, t, sx, sy, ex, ey, flag;
char map[10][10];
int vis[10][10];
int dir[4][2] = {{1, 0}, {0, 1}, {-1, 0}, {0, -1}};
void dfs(int x, int y, int ti)
{
int dx, dy;
if (flag == 1 || ti > t)
return;
// 在规定时间内正好到达终点
if (map[x][y] == 'D' && ti == t)
{
flag = 1; // 找到了这么一条路
return; // 返回
}
int tem = t - ti - abs(ex - x) - abs(ey - y); //剪枝的核心代码
if (tem < 0 || tem & 1) //剪枝:如果剩余的步数已经不足以走到出口,且必须是偶数,偶数-偶数=偶数,奇数-奇数=偶数,
return;
// 四个方向遍历
for (int i = 0; i < 4; ++i)
{
dx = x + dir[i][0];
dy = y + dir[i][1];
// 如果 越界 或 走到墙X 或 已访问过
if (dx < 0 || dx >= n || dy < 0 || dy >= m || map[dx][dy] == 'X' || vis[dx][dy])
continue;
// 新扩展的点标记走过, 对该点进行DFS
vis[dx][dy] = 1;
dfs(dx, dy, ti + 1);
// 回溯后将标记撤回
vis[dx][dy] = 0;
}
return;
}
int main()
{
while (cin >> n >> m >> t)
{
if (n == 0 && m == 0 && t == 0)
break;
memset(vis, 0, sizeof(vis));
for (int i = 0; i < n; ++i)
{
cin >> map[i];
}
int wall = 0;
flag = 0;
for (int i = 0; i < n; i++)
{
for (int j = 0; j < m; j++)
{
if (map[i][j] == 'S')
{
sx = i;
sy = j;
}
if (map[i][j] == 'D')
{
ex = i;
ey = j;
}
if (map[i][j] == 'X')
wall++;
}
}
if (t > n * m - wall - 1)
{
cout << "NO" << endl;
continue;
}
vis[sx][sy] = 1;
dfs(sx, sy, 0);
if (flag)
cout << "YES" << endl;
else
cout << "NO" << endl;
}
return 0;
}