迷宫大家都知道是可以用通过dfs(深度优先算法)进行解决,现在问题如下:小明参加了一个迷宫游戏,这个游戏有这样一个规则:小明只能向上下左右方向任意走n步(可以走回头路),现在需要知道这任意的n步所能覆盖的点的范围和这n步所有的路径
基本原理
经过推理,任意走n步(可以走回头路)有一个规律,那就是所有点构成的图形是一个旋转45度的正方形,如下图所示
并且从图上可以发现一个规律就是不管从哪个点走,走n步后走到的点的个数为(n+1)^2, 经过测试这个规律是正确的。
那么现在问题又来了,如何去获取这些点的坐标和所有到达的路径呢?
获取点的坐标【难度:简单】
思路如下:
- 输入坐标(x,y)和要走的步数
- 利用递归实现上下左右四个方向随意走动的功能,每走一步步数减一
- 当步数为0时输出当前的点的坐标
代码如下:
/**
* 深度遍历某一个位置走nbStep后的点坐标
* @param x 初始时的横坐标,注意这里为二维数组的第二维度
* @param y 初始时的纵坐标,注意这里为二维数组的第一维度
* @param nbStep 第几步
* direction 方向 ( 规定 1- 向右,2-向下, 3-向左,4-向上)
* @return 所到达的点坐标集合
*/
public static List<String> DFSResult(
int x, int y, int nbStep
) {
List<String> result = DFSResult(
x, y, nbStep, new ArrayList<String>()
);
return result;
}
private static List<String> DFSResult(
int x, int y, int nbStep, List<String> result
) {
if (nbStep == 0) {
String res = "(" + x + "," + y + ")";
if (!result.contains(res)) {
result.add(res);
}
return result;
}
int nextX = 0, nextY = 0;
for (int direction = 1; direction < 5; direction++) {
switch(direction) {
case 1: nextX = x + 1; nextY = y; break;
case 2: nextX = x; nextY = y + 1; break;
case 3: nextX = x - 1; nextY = y; break;
case 4: nextX = x; nextY = y - 1; break;
}
DFSResult(nextX,nextY, nbStep - 1, result);
}
return result;
}
输入:
原点坐标(4,4)
要走的步数 2
输出:
(6,4)
(5,5)
(4,4)
(5,3)
(4,6)
(3,5)
(2,4)
(3,3)
(4,2)
获取所有到达的路径【难度:困难】
思路:
- 利用stack(栈)的先进后出原理存储每个路径上的点
- 每次走一步前将要到达的点存入stack中
- 当前节点上下左右都递归完毕后就返回前一节点继续后续的递归,这里要pop一下
代码如下:
/**
* 深度遍历某一个位置走nbStep后的路径
* @param x 初始时的横坐标,注意这里为二维数组的第二维度
* @param y 初始时的纵坐标,注意这里为二维数组的第一维度
* @param nbStep 第几步
* direction 方向 ( 规定 1- 向右,2-向下, 3-向左,4-向上)
*/
//node 为路径上的节点
private class Node{
int x;
int y;
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
public int getY() {
return y;
}
public void setY(int y) {
this.y = y;
}
public Node(int x, int y) {
super();
this.x = x;
this.y = y;
}
@Override
public String toString() {
return "Node [x=" + x + ", y=" + y + "]";
}
}
//用栈存放路径的节点
private static Stack<Node> stackNode = new Stack<>();
private static List<String> DFSRoute(
int x, int y, int nbStep
) {
List<String> res = new ArrayList<>(); // 返回结果
// 如果是最后一个位置就返回路径
if (nbStep == 0) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < stackNode.size(); i++) {
Node node = stackNode.get(i);
if (i == stackNode.size() - 1) {
sb.append("(" + node.getX() + "," + node.getY() + ")");
} else {
sb.append("(" + node.getX() + "," + node.getY() + ") => ");
}
}
res.add(sb.toString());
stackNode.pop(); //弹出最后一个元素
return res;
}
Node node = new Path().new Node(x, y);
if (stackNode.size() == 0) {
stackNode.push(node);
}
int nextX = 0, nextY = 0;
// 前后左右走一遍
for (int direction = 1; direction < 5; direction++) {
switch(direction) {
case 1: nextX = x + 1; nextY = y; break;
case 2: nextX = x; nextY = y + 1; break;
case 3: nextX = x - 1; nextY = y; break;
case 4: nextX = x; nextY = y - 1; break;
}
// 将将要走上的点存入stack中
Node node1 = new Path().new Node(nextX, nextY);
stackNode.push(node1);
//开启下一个递归,将结果保存在res中
res.addAll(DFSRoute(nextX,nextY, nbStep - 1));
}
// 关键点:每次前后左右都走了一遍后就返回前一节点
stackNode.pop();
return res;
}
输入:
原点坐标(4,4)
要走的步数 2
输出:
(4,4) => (5,4) => (6,4)
(4,4) => (5,4) => (5,5)
(4,4) => (5,4) => (4,4)
(4,4) => (5,4) => (5,3)
(4,4) => (4,5) => (5,5)
(4,4) => (4,5) => (4,6)
(4,4) => (4,5) => (3,5)
(4,4) => (4,5) => (4,4)
(4,4) => (3,4) => (4,4)
(4,4) => (3,4) => (3,5)
(4,4) => (3,4) => (2,4)
(4,4) => (3,4) => (3,3)
(4,4) => (4,3) => (5,3)
(4,4) => (4,3) => (4,4)
(4,4) => (4,3) => (3,3)
(4,4) => (4,3) => (4,2)
写的不足之处欢迎指出,也欢迎联系我qq:271527068