[英]Solving a Sudoku field with Recursion and Backtracking in C
我的挑战是用递归和回溯解决给定的数独领域。 我们已经有一些代码,但我们不知道如何实现回溯。 这是我们的代码:
int solve( int row, int col ) {
if (getValueFromField(row, col) != 0) {
if (col < 8) {
return solve(row, col + 1);
}
if (col == 8) {
return solve(row + 1, 0);
}
if (col == 8 && row == 8) {
return 1;
}
} else {
for (int i = 1; i <= 9; i++) {
if (checkValueInField(i, row, col)) {
setValueInField(i, row, col);
if (solve(row, col)) {
continue;
}
return solve(row, col + 1);
}
}
removeValueFromField(row, col);
return 0;
}
return -1;
}
removeValueFromField()
、 setValueInField()
等方法可以自行解释。 如果没有,我可以向您解释他们的工作。
您对如何在此处实施回溯有想法吗? 问候! 拉斐尔
您必须将之前所做的检查保存在每个单元格的可能值列表中。 最初,所有列表都包含数字 1-9。 初始化后,数独中给定单元的列表减少为一个成员。
然后,主要算法是对所有单元格的循环,您可以将其实现为递归,就像在您的代码中一样。 在此循环中,所有数独约束都应用于每个列表,并删除了不兼容的情况。 例如:假设 cell(1,1) 为 '1',那么我们可以从第 1 行、第 1 列、块 (1,1) 等的所有列表中删除 1。我们循环直到没有不兼容的情况存在。 如果列表之一折叠为零长度,则数独是无法解决的。
如果在这一点 (A) 两个或多个列表的长度保持大于 1,我们选择其中一个列表的可能性之一(例如 p),并再次开始循环。 如果事实证明这是无法解决的,我们从列表中删除 p,返回到 (A)(这是回溯)并尝试第二种可能性,等等。最终我们将达到一个阶段,除了一个列表之外,所有列表的长度都为 1。 如果最后一个列表的长度 > 0,则数独是可解的。
这是一个简化版本,它只是找到了一种可能的解决方案。 您必须自己编写原型函数。
int getListLength(row, col); // number of possible values for this cell, 0...9
void checkConstrains(); // loop all sets (rows, columns, blocks)
// and find lists with one element. Remove
// this element from all other lists in the set.
// Repeat until no duplicates are found.
int *savelist(row, col); // make a copy of the list
void setlist(row, col, k); // set list of cell to { k }
getstate(), setstate(s); // save and set state of the game, ie. all lists
int solve( int row, int col ) {
int length = getListLength(row, col);
if(length == 0)
return 0; // unsolveable
// this is your recursion step slightly
// reordered to avoid row-overflow
if (col == 8 && row == 8) {
return 1;
}
int next_row, next_col;
if(col < 8) {
next_row = row;
next_col = col + 1;
} else {
next_row = row + 1;
next_col = 0;
}
if(length == 1) {
return solve(next_row, next_col);
}
// if we reach this step: length > 1
checkConstrains();
// length might have changed
length = getListLength(row, col);
if(length == 0)
return 0;
if(length == 1)
return solve(next_row, next_col);
// still: length > 1
// backtracking stage
int* list = savelist(row, col);
sudoku s = getstate();
for(int i = 0; i < length; i++) {
setstate(s);
setlist(row, col, list[i]);
if(solve(row, col))
return 1;
}
// all elements from list failed-->unsolveable
// free list and s
return 0;
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.