[英]I am having trouble with my recursive backtracking algorithm for solving sudoku in C
我可以解决一个简单的难题,但尝试稍微困难一点是不可能的; 我在俯视什么? 这是我的求解器方法:
int solver (int x, int y)
{
int a, b, i, j;
for (a=1; a<10; a++)
{
if (checkEverything(x, y, a))
{
board[x][y] = a;
counter++;
if (counter == 81)
{
return true;
}
if (x == 9)
{
return true;
}
if (counter > 200 || counter < -10) {
return false;
}
for (i=0; i<9; i++)
{
for (j=0; j<9; j++)
{
if (board[i][j] == 0)
{
if (solver(i, j))
{
return true;
}
}
}
}
counter--;
}
}
board[x][y] = 0;
return false;
}
我的checkEverything函数会检查以确保给定的数字可以安全地放置在行,列和3x3网格中...我很迷失,因为它似乎对我来说是正确的,但它是如此之慢。 谢谢你的帮助!
您的实现需要太多额外的检查。
当找到当前(x, y)
的当前有效候选者时,从棋board的开头找到下一个未确定的位置是多余的。
递归函数的复杂度将为O(N*N)*O(N)*M
(N是棋盘的边长,或checkEverything
是您的checkEverything
的复杂度)。在此表达式中, O(N*N)
是查找下一个不确定的位置,而O(N)
是尝试从1到N的每个数字的复杂度。我不知道如何实现checkEverything
,但是一个简单的实现将是M = O(N)
。 这意味着总复杂度可能约为O(N 4 )
有关优化的常见建议是:
降低寻找下一个位置O(1)
的复杂度。 您可以预处理棋盘,并预先将所有不确定的位置获取到列表中。
降低checkEverything
的复杂性。 通过使用一些哈希表来保存已使用的数字,可以将其简化为O(1)
,每列9个,每行9个,每个子矩形9个。
有了这两个建议,递归的复杂度将为O(N)
。
如果您想要完美的演奏,我建议您学习Knuth发明的Dancing Links。 该算法的主要思想是使用二维双向链表来存储所有位置的所有候选,并加快查找下一个位置和下一个候选,删除无效的候选并在回溯时恢复。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.