关于Java:机器人的所有可能路径

all possible paths for the robot

本问题已经有最佳答案,请猛点这里访问。

想象一下,一个机器人坐在NxN网格的左上角。机器人只能在两个方向上移动:向右和向下。想象一下,某些正方形是"限制范围",以至于机器人无法踩到它们。设计算法以获取机器人的所有可能路径。

这是我得到的参考实现,我认为该实现是错误的,因为它只找到一条路径,而不是所有可能的路径(更多详细信息,在第10行中,只有在没有正确的路径的情况下,机器人才会下降。)为了找到所有可能的路径,机器人应该同时尝试正确和向下的操作)?要确认我的理解是正确的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
ArrayList<Point> current_path = new ArrayList<Point>();
public static boolean getPaths(int x, int y) {
      Point p = new Point(x, y);
      current_path.add(p);
      if (0 == x && 0 == y) return true; // current_path
      boolean success = false;
      if (x >= 1 && is_free(x - 1, y)) { // Try right
        success = getPaths(x - 1, y); // Free! Go right
      }
      if (!success && y >= 1 && is_free(x, y - 1)) { // Try down
        success = getPaths(x, y - 1); // Free! Go down
      }
      if (!success) {
        current_path.remove(p); // Wrong way!
      }
      return success;
}

先谢谢了,


这是您可以做的:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
public  static class Point {
    int x, y;
    public Point (int x, int y) {
        this.x = x;
        this.y = y;
    }

    @Override
    public String toString() {
        return String.format("[%d, %d]", x, y);
    }
}

public static void getPathsRec(int x, int y, Deque<Point> currentPath,
                               List<List<Point>> paths) {
    if (x == 0 && y == 0) {
        List<Point> path = new ArrayList<Point>();
        for (Point p : currentPath)
            path.add(p);
        paths.add(path);
        //System.out.println(currentPath);
        return;
    }

    if (x > 0 && is_free(x-1, y)) {
        currentPath.push(new Point(x-1, y));
        getPathsRec(x-1, y, currentPath, paths);
        currentPath.pop();
    }

    if (y > 0 && is_free(x, y-1)) {
        currentPath.push(new Point(x, y-1));
        getPathsRec(x, y-1, currentPath, paths);
        currentPath.pop();
    }
}

static int n = 2;
public static List<List<Point>> getPaths() {
    List<List<Point>> paths = new ArrayList<List<Point>>();
    Deque<Point> d = new ArrayDeque<Point>();
    d.push(new Point(n-1, n-1));
    getPathsRec(n - 1, n - 1, d, paths);
    //System.out.println(paths);
    return paths;
}

这是一个简单的回溯。这个想法是递归地访问下一个状态,但是要确保在调用之后状态返回到其先前的状态(就像在调用之前一样)。这是通过从Deque弹出元素来完成的。

请注意,为简单起见,您可以引入新的类Path,该类类似于:

1
2
3
class Path {
    List<Point> points;
}

使代码更具可读性。然后getPaths()将返回List<Path>,这要好得多。

还可以考虑重新定义getPathsRec以使其具有签名getPathsRec(Point p, Deque<Point>, List<Path> ),即具有一个自变量Point而不是具有x, y。考虑到您已经定义了class Point的事实,使用x, y似乎是多余的。同样,这会使它看起来更好。


您的解决方案是错误的,因为一旦达到(0 == x && y==0)success值将始终设置为true。因此,以后将不再使用if

下面是您的问题的示例答案。它使用回溯算法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
public class test {
    static int n = 3; //substitute your n value here
    static ArrayList<Point> current_path = new ArrayList<Point>();
    static boolean[][] blockedCell = new boolean[n][n];
    public static void FindAllWay(int x, int y)
    {
        if (x <0 || y < 0) return;
        Point p = new Point(x, y);
        current_path.add(p);

        if (0 == x && 0 == y){
            System.out.println(current_path.toString());
            current_path.remove(current_path.size()-1);
            return;
        }

        if ((x > 0) && !blockedCell[x-1][y]) //go right
        {
            blockedCell[x-1][y] = true;
            FindAllWay(x-1, y);
            blockedCell[x-1][y] = false;
        }
        if ((y > 0) &&!blockedCell[x][y-1]) // go down
        {
            blockedCell[x][y-1] = true;
            FindAllWay(x, y-1);
            blockedCell[x][y-1] = false;
        }
        current_path.remove(current_path.size()-1);

    }

    public static void main(String[] args)
    {
        FindAllWay(n-1,n-1);
    }
}