一、题目描述
小明做了一个很久很久的梦,醒来后他竟发现自己和朋友在一个摇摇欲坠的大棋盘上,他们必须得想尽一切办法逃离这里。
经过长时间的打探,小明发现,自己所在的棋盘格子上有个机关,上面写着“你只有一次机会,出发后t秒大门会为你敞开”,而他自己所在的棋盘是大小为 N*M 的长方形,他可以向上下左右四个方向移动(不可走有障碍点)。棋盘中有一扇门。
根据机关的提示,小明顿时明白了,他和朋友必须在第 t 秒到门口。而这一切,没有回头路!因为一旦他移动了,他刚才所在的点就会消失,并且他不能在一个点上停留超过一秒,不然格子会爆炸。
大逃亡开始了,请问小明和朋友能安全的逃出这奇怪的棋盘吗?
Input
输入多组测试数据。每个测试用例的第一行包含三个整数 N、M 和 T ( 1 < N , M < 7 ; 0 < T < 50 ),分别表示棋盘的大小和门打开的时间。接下来的N行给出棋盘布局,每一行包含M个字符。其中
- “.”: 无障碍点
“X”: 障碍点
“S”: 起点
“D”: 门
输入以 3 个 0 结束。这个测试用例不需要处理。
Output
对于每组样例输出一行。
如果小明能够安全逃出,输出 “YES” ,否则输出 “NO”。
Sample Input
4 4 5
S.X.
..X.
..XD
....
3 4 5
S.X.
..X.
...D
0 0 0
Sample Output
NO
YES
二、题解
方法一:dfs 暴搜
- 常规 dfs,只能得 30pt。
- 小剪枝:当 reach = true 时,不必继续搜索。
import java.util.*;
import java.math.*;
import java.io.*;
public class Main{
static int N, M, T;
static int sx, sy, ex, ey;
static char[][] grid;
final static int[][] dir = { {0,1},{0,-1},{1,0},{-1,0} };
static boolean[][] vis;
static boolean reach;
static boolean inArea(int x, int y) {
return x >= 0 && x < N && y >= 0 && y < M;
}
static void dfs(int x, int y, int t) {
if (grid[x][y] == 'D') {
reach = t == T;
return;
}
if (reach) return;
for (int k = 0; k < 4; k++) {
int tx = x + dir[k][0];
int ty = y + dir[k][1];
if (!inArea(tx, ty) || grid[tx][ty] == 'X' || vis[tx][ty])
continue;
vis[tx][ty] = true;
dfs(tx, ty, t+1);
vis[tx][ty] = false;
}
}
public static void main(String[] args) throws IOException {
Scanner sc = new Scanner(new BufferedInputStream(System.in));
while (true) {
N = sc.nextInt();
M = sc.nextInt();
T = sc.nextInt();
if (N == 0 && M == 0 && T == 0)
break;
vis = new boolean[N][M];
grid = new char[N][M];
for (int i = 0; i < N; i++) {
String s = sc.next();
for (int j = 0; j < M; j++) {
grid[i][j] = s.charAt(j);
if (grid[i][j] == 'S') {
sx = i; sy = j;
} else if (grid[i][j] == 'D') {
ex = i; ey = j;
}
}
}
vis[sx][sy] = true;
dfs(sx, sy, 0);
System.out.println(reach ? "YES" : "NO");
reach = false;
}
}
}
可剪枝的地方:
- 预处理剪枝:当前位置
(x, y)
,那么当前可走的步数则为:T-t
,而两点之间最短距离,也叫曼哈顿距离则为abs(sx-ex) + abs(sy-ey)
,所以当T-t < abs(sx-ex) + abs(sy-ey)
时3 3 4 S X X . X X X . D 在这里n*m-obs = 3*3-5 = 4 = t,故不可达
- 奇偶剪枝:
复杂度分析
- 时间复杂度: ,注:回溯问题一般都不是线性复杂度。
- 空间复杂度: ,
方法二:bfs
这是个错误的选择,因为 bfs 报出来的一定是最短路,而最短路不一定就是要求时间 T。
参考博客:https://blog.csdn.net/nvliba/article/details/48532709,有图无码
10赞
文字解释
测评地址:https://vijos.org/d/orina_personal/p/5c4f2bf0f41362860e389f83