[英]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.