查找矩阵中是否存在路径

时间:2013-12-20 17:12:10

标签: java algorithm matrix

我必须生成一个5 x 5矩阵,随机值为0和1。

在这样的矩阵中,我必须找到从左到右存在由1组成的路径。相邻的1可以是垂直的,水平的或对角相邻的(也称为8连接)。

成功案例的一个例子是

1 0 0 1 0 
0 1 0 1 1 
1 1 1 1 0 
0 0 0 1 0 
1 1 0 1 1 

我已经生成了矩阵,并且发现很难确定路径。

我想到检查每个上/下/右/对角线索引= 1的值并继续前进。但在这种情况下,我不知道如何保持一条道路。

任何解决方案/算法都会非常有用。

4 个答案:

答案 0 :(得分:3)

修改 编辑修复了上一代码中的错误。从本质上讲,它会跟踪以前访问过的节点,以避免回溯,并在所有方向上搜索可能的其他路径。

使用受访节点,它还会跟踪经过的实际路径。

public static boolean hasPathHelper(int[][] m, int[][] v, int i, int j){
    if(i < 0 || j < 0 || i >= m.length || j >= m[0].length || v[i][j] >= 0)
        return false;                        // Index out of bounds

    v[i][j] = 0;                             // Mark as visited
    if(m[i][j] == 0)                         // Path stops here
        return false;
    if(j == m[0].length - 1 ||               // Right side reached!
       hasPathHelper(m, v, i - 1, j + 1) ||  // Check upper right
       hasPathHelper(m, v, i + 1, j + 1) ||  // Check lower right
       hasPathHelper(m, v, i + 1, j - 1) ||  // Check lower left
       hasPathHelper(m, v, i + 1, j - 1) ||  // Check upper left
       hasPathHelper(m, v, i + 1, j    ) ||  // Check down
       hasPathHelper(m, v, i - 1, j    ) ||  // Check up
       hasPathHelper(m, v, i    , j + 1) ||  // Check right
       hasPathHelper(m, v, i    , j - 1)     // Check left
    ) v[i][j] = 1;                           // Mark as good path

    return v[i][j] == 1;
}

public static boolean hasPath(int[][] m, int[][] v){
    for(int i = 0; i < m.length; i++)
        if(hasPathHelper(m, v, i, 0))
            return true;

    return false;
}

public static void main(String... args){
    int[][] m = { {0,1,1,1,0},
                  {1,0,0,1,0},
                  {0,0,1,1,0},
                  {0,1,0,0,0},
                  {0,0,1,1,1} };

    int[][] v = new int[5][5];                         // v => -1, not visited
    for(int i=0; i<5; i++)                             // v =>  0, visited bad path
        Arrays.fill(v[i], -1);                         // v =>  1, visited good path

    System.out.println("Has Path?: " + hasPath(m, v));
    System.out.println("Path Matrix: ");
    for(int i = 0; i < v.length; i++)
        System.out.println(Arrays.toString(v[i]));    
}

输出

Has Path?: true
Path Matrix: 
[ 0,  1,  1, -1,  0]
[ 1,  0,  0,  1, -1]
[-1, -1,  1, -1,  0]
[-1,  1,  0,  0,  0]
[-1, -1,  1,  1,  1]

答案 1 :(得分:0)

递归是你的朋友(伪):

boolean existsPath(field, from, to)
{
    if (field[from] == 0) return false;
    if (from == to) return true;
    if (existsPath(field, from + up, to)) return true;
    if (existsPath(field, from + down, to)) return true;
    if (existsPath(field, from + right, to)) return true;
    if (existsPath(field, from + diag, to)) return true;

    return false;
}

粗略地说,这样的事情会对你有所帮助。 您需要额外检查,以防止您在同一时间来两次。

答案 2 :(得分:0)

您应该查看Graph Traversal算法。深度优先搜索可能最容易实现。我不会给你代码,所以你可以学到一些东西。到目前为止提交的所有三个都不是完全正确的。

在您的情况下,DFS将如下所示(在伪代码中):

search(i, j, path)
  if [i,j] is off the matrix, return null
  return null if a[i,j] already marked;
  if j == 3, return path
  mark a[i,j]
  new_path = path :: <i,j> // append the pair <i,j> on the path list

  return search(i + 1, j + 1) unless its value is null
  return search(i + 1, j)     unless its value is null
  return search(i + 1, j - 1) unless its value is null

  return search(i - 1, j + 1) unless its value is null
  return search(i - 1, j)     unless its value is null
  return search(i - 1, j - 1) unless its value is null

  return search(i, j + 1) unless its value is null
  return search(i, j - 1)   

标记搜索路径的一种简单方法是将所有1改为-1或类似的东西。

答案 3 :(得分:0)

构造一个2D访问boolean数组,其中包含与输入数组大小相同的所有false值。

现在检查输入数组每行的第一个单元格 如果该单元格为1且未设置相应的访问单元格:

  • 将该单元格添加到Stack
  • 虽然堆栈不是空的:
    • 从堆栈弹出。
    • 如果弹出的单元格在右侧,我们找到了一条路径。
    • 将弹出的单元格的访问值设置为true。
    • 将该单元格中值为1的所有未访问的邻居添加到堆栈中。

这称为depth-first search

这也应该相当容易递归(但递归函数的高级描述稍微困难一些)。