我的问题本质上是关于递归的疑问。我正在解决经典的“迷宫中的老鼠” DFS遍历问题。我的输入是一个n*n int
数组a[][]
,其中对于索引i
和j
,a[i][j]
可以是0
或1
。 0
表示假设的老鼠无法访问该元素,而1
意味着可以访问该元素。老鼠只能向下("D"
)或向右("R"
)走。任务是输出表示RDRDRD
之类的所有运动字符串,它们代表大鼠在迷宫中的运动。老鼠从a[0][0]
开始,必须到达a[n-1][n-1]
。输入的是迷宫本身。
我写了以下代码
public boolean isSafe(int x, int y, int[][] a, int n)
{
if(x >= 0 && x < n && y >= 0 && y < n && a[x][y] == 1)
return true;
else
return false;
}
public ArrayList<String> printPath(int[][] a, int n)
{
ArrayList<String> res = new ArrayList<String>();
solve(0,0,new String(), res,a,n);
return res;
}
public void solve(int x, int y, String sol, ArrayList<String> res ,
int[][]a, int n)
{
if(x == n-1 && y == n-1)
{
res.add(sol);
return;
}
y++;
if(isSafe(x,y,a,n))
{
solve(x,y,sol + "R",res,a,n);
}
else
y--;
x++;
if(isSafe(x,y,a,n))
{
solve(x,y,sol+"D",res,a,n);
}
else
x--;
}`
其中isSafe
检查是否允许移动,printPath
是用于打印输出的辅助函数,solve
是用于遍历迷宫的递归函数。a
将迷宫数组表示为二维数组。
对于输入
{1 0 0 0
1 1 0 1
0 1 0 0
0 1 1 1}
我得到以下输出
DRDDRR DDDRR
很明显,第二个字符串表示错误的结果。
但是,当我像这样更改solve
函数时
public void solve(int x, int y, String sol, ArrayList<String> res,
int[][]a, int n)
{
if(x == n-1 && y == n-1)
{
res.add(sol);
return;
}
if(!isSafe(x,y,a,n))
return;
solve(x+1,y,sol + "D",res,a,n);
solve(x,y+1,sol + "R",res,a,n);
return;
}
我得到正确的输出。我无法理解的是在我以前的解决方案中导致错误输出的原因,因为我认为这两种解决方案在逻辑上是相似的。 我知道这是一本很长的书,但是任何见解都将不胜感激。
答案 0 :(得分:1)
在第一个解决方案中,仅当对具有递增值的y++
的调用返回为负时,变量增量isSafe
才被撤消,如果是,则继续进行x
的检查。真正。这意味着将对具有有效相邻项右边的字段(特别是字段[1] [0])执行向下检查,而递增的值将是y
,而不是正确的值。>
如果您这样修改第一个解决方案
y++;
if(isSafe(x,y,a,n)){
solve(x,y,sol + "R",res,a,n);
}
y--;
第一个解决方案将与第二个解决方案正常工作。在第二种解决方案中,增量仅在函数参数上完成,而不是在局部变量上完成。
答案 1 :(得分:1)
一般建议不要修改您的输入。在这种情况下,您的问题仅来自此。在这里,我修改了您的代码,所以它没有这样做。在我看来,它更具可读性,现在您可以确定要使用的x或y值。
if (isSafe(x, y + 1, a, n)) {
solve(x, y + 1, sol + "R", res, a, n);
}
if (isSafe(x + 1, y, a, n)) {
solve(x + 1, y, sol + "D", res, a, n);
}