家庭作业 - 通过int方法回溯

时间:2016-02-18 23:10:05

标签: java recursion multidimensional-array backtracking

以下代码旨在通过最快的路线将您从[0,0]转移到[a.length-1][a[0].length-1]。规则是你只能向前推进\ right \ up \ down,下一个单元格必须>(大于)当前单元格。

    private static int path(int[][]a,int i, int j, int count)
    {
        if((i==a.length-1)&&(j==a[0].length-1))
            return count+1;
        if((j<a[0].length-1)&&(a[i][j]<a[i][j+1]))
            if(canPass(a,i,j+1))
                return (path(a,i,j+1,count+1));
        if((i<a.length-1)&&(a[i][j]<a[i+1][j]))
            if(canPass(a,i+1,j))
                return path(a,i+1,j,count+1);
        if((i>0)&&(a[i][j]<a[i-1][j]))
            if(canPass(a,i-1,j))
                return path(a,i-1,j,count+1);
        if((j>0)&&(a[i][j]<a[i][j-1]))
            if(canPass(a,i,j-1))
                return path(a,i,j-1,count+1);
         return -1;
private static boolean canPass(int[][]a,int i,int j)
    {
        if((i==a.length-1)&&(j==a[0].length-1))
            return true;
        if((j<a[0].length-1)&&(a[i][j]<a[i][j+1]))
                 if(canPass(a,i,j+1))
                    return true;
         if((i<a.length-1)&&(a[i][j]<a[i+1][j]))
                 if(canPass(a,i+1,j))
                    return true;
         if((i>0)&&(a[i][j]<a[i-1][j]))
                 if(canPass(a,i-1,j))
                    return true;
         if((j>0)&&(a[i][j]<a[i][j-1]))
                 if(canPass(a,i,j-1))
                    return true;
         return false;
        }
public static void main(String args[])//DRIVER
    {    
       int[][] multi = new int[][]{
  { 3, 13, 15, 28, 30 },
  { 40, 51, 52, 29, 30 },
  { 28, 10, 53, 54, 53 },
  { 53, 12, 55, 53, 60 },
  { 70, 62, 56, 20, 80 },
  { 80, 81, 90, 95, 100 },
};
System.out.println(path(multi));   

此代码有效。但是,有两件我不满意的事情,非常感谢你的帮助:

  1. 方法结束时的return -1行 - 它基本上从未被调用过吗?我该如何避免呢?

  2. 使用布尔方法 - 我试图仅使用int方法使回溯工作,但无法找到解决方案。

  3. 谢谢!

1 个答案:

答案 0 :(得分:1)

你的递归实现可以使用一些工作,或者更少的工作!

canPass函数中,您可以对网格进行整个递归计算。您可以在此处完成所有必要的工作以找到有效的路径。如果路径可行,则在path函数中移动一个块,忘记所做的所有工作。在下一步中,您将再次重新评估整个网格。这是太多的工作方式,随着网格的大小增加,你的实现将变得非常缓慢。

理想情况下,对于此程序,您只需要一个递归函数。 canPass函数应该告诉您下一个方格是否可行。它确实只存在,因此您不必连续4次写出条件。如果没有可能的路径,则返回-1表示它无效。而且,不要将计数传递给其他函数,只需在返回时增加它。

以下是一个示例方法:

public static boolean canPass(int[][]a, int i, int j, int oldValue){
    if((j >= a[0].length) || (j < 0) || (i >= a.length) || (i < 0)){
        return false;
    }
    return a[i][j] > oldValue;
}

// added a helper function to reduce repetitive code
public static int chooseShortest(int nextPath, int currentPath){
    if (nextPath != -1){
        if (currentPath == -1 || currentPath > nextPath){
                return nextPath;
            }
        }
    }
    return currentPath;
}

public static int path(int[][]a, int i, int j)
{
    // This is the end condition
    // there is one step left so return 1
    if((i == a.length - 1) && (j==a[0].length - 1)){
        return 1;
    }

    int shortestPath = -1;

    if (canPass(a, i, j + 1, a[i][j])){
        shortestPath = chooseShortest(path(a, i, j + 1), shortestPath);
    }
    if (canPass(a, i, j - 1, a[i][j])){
        shortestPath = chooseShortest(path(a, i, j - 1), shortestPath);
    }
    if (canPass(a, i + 1, j, a[i][j])){
        shortestPath = chooseShortest(path(a, i + 1, j), shortestPath);
    }
    if (canPass(a, i - 1, j, a[i][j])){
        shortestPath = chooseShortest(path(a, i - 1, j), shortestPath);
    }
    // if all 4 paths return -1 there is no path possible from here
    if (shortestPath == -1){
        return -1;
    }

    // return the shortest path + 1 step to get there
    return shortestPath + 1;
}
相关问题