簡體   English   中英

我無法使用遞歸回溯算法解決C中的數獨問題

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

有關優化的常見建議是:

  1. 降低尋找下一個位置O(1)的復雜度。 您可以預處理棋盤,並預先將所有不確定的位置獲取到列表中。

  2. 降低checkEverything的復雜性。 通過使用一些哈希表來保存已使用的數字,可以將其簡化為O(1) ,每列9個,每行9個,每個子矩形9個。

有了這兩個建議,遞歸的復雜度將為O(N)

如果您想要完美的演奏,我建議您學習Knuth發明的Dancing Links。 該算法的主要思想是使用二維雙向鏈表來存儲所有位置的所有候選,並加快查找下一個位置和下一個候選,刪除無效的候選並在回溯時恢復。

http://en.wikipedia.org/wiki/Dancing_Links

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM