以下代码旨在通过最快的路线将您从[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));
此代码有效。但是,有两件我不满意的事情,非常感谢你的帮助:
方法结束时的return -1
行 - 它基本上从未被调用过吗?我该如何避免呢?
使用布尔方法 - 我试图仅使用int
方法使回溯工作,但无法找到解决方案。
谢谢!
答案 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;
}