我想实现一个使用暴力回溯算法来解决数独网格的简单算法。我遇到的问题是,在我的实现中,我为Sudoku类包含了两个实例变量,称为row和col,它们对应于表示数独网格的二维数组中空单元格的行和列。
当我的solve()方法执行时,它首先检查是否有任何空单元格,如果有,则谜题已经完成。否则,该方法将空单元格的行和列分配给包含网格的Sudoku对象的实例变量row和col。之后,for循环通过调用isSafe(int n)方法验证可以在该空单元格中放置哪个数字(此方法检查是否满足谜题的约束条件,我可以保证它完美地运行)。因此,isSafe()方法将数字放置在空单元格中,然后再次在Sudoku对象上对solve()方法进行递归调用。
如果我们遇到无法满足的约束,则将0重新分配给最后一个填充的row和col。这就是问题所在!由于程序不断更新row和col变量,因此每个递归调用都会丢失旧实例。我一直在努力找出如何存储这些值,以便程序在回溯时可以撤消操作。我考虑将每个col和row推入堆栈,但我真的不确定该去哪里。
有人能告诉我解决这个问题的简单方法吗?如果您认为包含整个类会有帮助,请告诉我,我会发布它。
当我的solve()方法执行时,它首先检查是否有任何空单元格,如果有,则谜题已经完成。否则,该方法将空单元格的行和列分配给包含网格的Sudoku对象的实例变量row和col。之后,for循环通过调用isSafe(int n)方法验证可以在该空单元格中放置哪个数字(此方法检查是否满足谜题的约束条件,我可以保证它完美地运行)。因此,isSafe()方法将数字放置在空单元格中,然后再次在Sudoku对象上对solve()方法进行递归调用。
如果我们遇到无法满足的约束,则将0重新分配给最后一个填充的row和col。这就是问题所在!由于程序不断更新row和col变量,因此每个递归调用都会丢失旧实例。我一直在努力找出如何存储这些值,以便程序在回溯时可以撤消操作。我考虑将每个col和row推入堆栈,但我真的不确定该去哪里。
有人能告诉我解决这个问题的简单方法吗?如果您认为包含整个类会有帮助,请告诉我,我会发布它。
class Sudoku {
int SIZE, N, row, col;
int Grid[][];
public boolean solve() {
if (!this.findNextZero()) return true;
for (int num = 1; num <= 9; num++) {
if (isSafe(num)) {
this.Grid[this.row][this.col] = num;
if (this.solve()) return true;
this.Grid[this.row][this.col] = 0;
// this.Grid[oldRow][oldCol] = 0;
}
}
return false;
}
public boolean findNextZero() {
for (int i = 0; i < this.N; i++) {
for (int j = 0; j < this.N; j++) {
if (this.Grid[i][j] == 0) {
this.row = i;
this.col = j;
return true;
}
}
}
return false;
}
public boolean isSafe(int num) {
return !this.usedInRow(num)
&& !this.usedInColumn(num)
&& !this.usedInBox(num);
}
如果我要实现一个栈,以下内容是否有意义?在 findNextZero()
操作之后将 row
和 col
整数推入栈中。继续这样做,然后修改下面的代码行。
this.Grid[this.row][this.col] = 0;
转换为类似于
this.Grid[s.pop][s.pop] = 0;
这种方法合理吗?