我轻松地制作了数独检查器/求解器,但是我需要一个可以告诉我有多个解决方案,并且无法绕过它的人。我找到了一个有效的算法,但我试图理解它为什么会起作用。这是this question的答案,由@fabian提供
复制如下:
// returns 0, 1 or more than 1 depending on whether 0, 1 or more than 1 solutions are found
static byte solve(int i, int j, int[][] cells, byte count /*initailly called with 0*/) {
if (i == 9) {
i = 0;
if (++j == 9)
return 1+count;
}
if (cells[i][j] != 0) // skip filled cells
return solve(i+1,j,cells, count);
// search for 2 solutions instead of 1
// break, if 2 solutions are found
for (int val = 1; val <= 9 && count < 2; ++val) {
if (legal(i,j,val,cells)) {
cells[i][j] = val;
// add additional solutions
count = solve(i+1,j,cells, count));
}
}
cells[i][j] = 0; // reset on backtrack
return count;
}
我尝试实现它,并且应该如此,它可以工作。但是,虽然我认为我理解代码的每个部分的内容,但我无法理解其工作原理。
首先:一旦达到2d数组中的最终数字,第一个if
语句就会停止该方法。我找到了一个解决方案,但为什么它可以找到多个解决方案呢?在找到解决方案后,该方法不应该返回0 + 1 = 1吗?
第二次:if (cells[i][j] != 0)
之后,为什么递归solve(...)
调用需要return
语句?我已经制作了几个递归算法,但总是只需再次调用该方法。
第三:如果没有找到合适的数字,for
循环停止,0输入到单元格位置。既然它应该已经有0,那么回溯是否应该将0放到最后一个位置而不是当前?至少这就是我自己制作解算器的方式。
第四个:在回溯设置之后,只有return count
。为什么程序仍然有效?难道它不会返回count = 0并且在面对不允许任何数字的第一个位置后停止吗?如果最后没有递归电话?
如果你在这个棘手的问题上做到这一点,很明显,我对某些事情的理解是完全错误的。我非常感谢您的帮助/解释,因为在学习代码的过程中使用代码并不能完全理解。
答案 0 :(得分:0)
好的,所以Google优雅地提供了哈佛大学的Powerpoint讲座: http://www.fas.harvard.edu/~cscie119/lectures/recursion.pdf
如果其他人遇到递归回溯问题,我建议您查看。很短但信息量很大。
我的问题似乎只是我愚蠢地(至少在后见之明)假设该方法在递归调用自身后停止。我忘了它从它产生的递归调用得到结果后,它会自己执行到最后。有趣的是你如何使用umphteen小时解决问题只是因为你最初的思考过程是有缺陷的。嗯,生活和学习我猜。