【发布时间】:2016-02-07 14:58:11
【问题描述】:
我之所以创建这个新线程,而不是仅仅阅读之前给出的这个特定问题的答案,是因为我觉得我只是不完全理解它背后的整个想法。我似乎无法理解整个回溯的概念。所以我需要充分理解回溯,然后解决特定的数独问题。
到目前为止,我所理解的是,如果发现在当前状态之前做出的决定导致了死胡同,则回溯是一种返回的技术,在(例如)递归流程中。所以你回去试试别的,然后再继续。
因此,在我的数独示例中,我选择了第一个空单元格并尝试从 {1...9} 中填充一个自然数,该自然数与众所周知的数独规则不冲突。现在我对下一个空单元格做同样的事情,直到我没有插入有效数字而不会发生冲突。据我了解,这应该是回溯发挥作用的地方。但是怎么做?如果我使用递归返回最后写入的单元格,算法将再次填写数字,继续并最终陷入无限循环。
所以我在 Internet 上搜索了提示,发现这是一个有据可查且经常解决的问题。然而,许多解决方案声称使用回溯,即使我面前有源代码,我也不知道它们是如何或在何处使用的。
例如:Sudoku solver in Java, using backtracking and recursion 或 http://www.heimetli.ch/ffh/simplifiedsudoku.html
这是我的(不工作的)源代码:
private boolean isSolvable( Sudoku sudoku, int row, int col ){
//if the method is called for a row > 8 the sudoku is solved
if(row > 8)
return true;
//calculate the next cell, jump one row if at last column
int[] nextCell = (col < 8) ? new int[]{row,col+1} : new int[]{row+1,0};
//check if the current cell isWritable() that is if it is not a given cell by the puzzle
//continue recursively with the next cell if not writable
if(!sudoku.isWritable(row, col))
isSolvable(sudoku, nextCell[0], nextCell[1]);
else{
//set the current cell to the lowest possible not conflicting number
for(int i=1; i< 10; i++){
if(!conflictAt(sudoku, row, col, i)){
sudoku.setValue(row, col, i);
//continue recursively with the next cell
isSolvable(sudoku, nextCell[0], nextCell[1]);
}
}
}
return false;
}
现在我不知道如何继续。如何实施回溯或者我已经实施了吗?这似乎是一个愚蠢的问题,但我真的没有看到上面链接中提到的源代码中有更多的回溯。
编辑:最终(工作)版本:
private boolean isSolvable( Sudoku sudoku, int row, int col ){
//if the method is called for a row > 8 the Sudoku is solved
if(row > 8)
return true;
//if the cell is not writable, get the next writable cell recursively
if(!sudoku.isWritable(row,col))
return isSolvable(sudoku, (col<8) ? row : row + 1, (col<8) ? col + 1 : 0);
//brute forcing for solution
for(int i=1; i<=9; i++){
if(!conflictAt(sudoku, row, col, i)){
sudoku.setValue(row, col, i);
if(isSolvable(sudoku, (col<8) ? row : row + 1, (col<8) ? col + 1 : 0)) return true;
}
}
sudoku.setValue(row, col, 0);
return false;
}
【问题讨论】:
-
您可以使用各种策略直接解决问题,而不是猜测解决方案:github.com/cyrixmorten/sudoku。如果遇到死胡同(如回溯),这也留下了交换策略的选项。您可以查看项目中的单元测试以查看添加新策略以解决困难数独的示例。此实现的另一个好处是能够让用户逐步推理如何找到解决方案。
-
嗨,我知道有更好、更有效的方法来解决这个问题。我是一名 Java 新手和计算机科学专业的学生(第一学期),因此需要了解这个确切的实现。
-
好吧,我明白了,那么当你需要考虑基本的软件架构时,你可能想看看我的项目 :) 似乎是第一学期的一个很好且相当高级的作业。
-
我可能会的,谢谢。 :)
标签: java recursion sudoku backtracking recursive-backtracking