简体   繁体   English

我无法使用递归回溯算法解决C中的数独问题

[英]I am having trouble with my recursive backtracking algorithm for solving sudoku in C

I can solve an easy puzzle but attempting a slightly harder one is impossible; 我可以解决一个简单的难题,但尝试稍微困难一点是不可能的; what am I overlooking? 我在俯视什么? Here is my solver method: 这是我的求解器方法:

   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;

    }

My checkEverything function checks to make sure that the given number is safe to be placed in the row, column, and 3x3 grid...I am very lost because it seems to be right to me but it is so slow. 我的checkEverything函数会检查以确保给定的数字可以安全地放置在行,列和3x3网格中...我很迷失,因为它似乎对我来说是正确的,但它是如此之慢。 Thanks for any help! 谢谢你的帮助!

Your implementation takes too much extra checking. 您的实现需要太多额外的检查。

When finding a current valid candidate for current (x, y) , it is redundant to find the next undetermined position from the beginning of the chessboard. 当找到当前(x, y)的当前有效候选者时,从棋board的开头找到下一个未确定的位置是多余的。

The complexity for your recursive function will be O(N*N)*O(N)*M (N is the side length of the chessboard, or 9. M is the complexity of your checkEverything ).In this expression, O(N*N) is to find the next undetermined position and O(N) is the complexity of try every digit from 1 to N. I don't know how you implement checkEverything , but a naive implement will be M = O(N) . 递归函数的复杂度将为O(N*N)*O(N)*M (N是棋盘的边长,或checkEverything是您的checkEverything的复杂度)。在此表达式中, O(N*N)是查找下一个不确定的位置,而O(N)是尝试从1到N的每个数字的复杂度。我不知道如何实现checkEverything ,但是一个简单的实现将是M = O(N) That means the total complexity may be about O(N 4 ) 这意味着总复杂度可能约为O(N 4

The common advices for optimization will be: 有关优化的常见建议是:

  1. reduce the complexity of finding the next position to be O(1) . 降低寻找下一个位置O(1)的复杂度。 You can preprocess the chessboard and obtain all of the undetermined positions into an list in advance. 您可以预处理棋盘,并预先将所有不确定的位置获取到列表中。

  2. reduce the complexity of checkEverything . 降低checkEverything的复杂性。 It can be reduced into O(1) by using some hash tables to hold digits already used, 9 for the each column, 9 for each row, 9 for each sub rectangle. 通过使用一些哈希表来保存已使用的数字,可以将其简化为O(1) ,每列9个,每行9个,每个子矩形9个。

With this two advice, the complexity of the recursive will be O(N) . 有了这两个建议,递归的复杂度将为O(N)

If you want a perfect performance, I advice you to learn Dancing Links invented by Knuth. 如果您想要完美的演奏,我建议您学习Knuth发明的Dancing Links。 The main idea of this algorithm is using a 2 dimension double linked list to store all candidate of all positions and accelerate finding the next position and the next candidate, delete invalid candidates and recover when backtracing. 该算法的主要思想是使用二维双向链表来存储所有位置的所有候选,并加快查找下一个位置和下一个候选,删除无效的候选并在回溯时恢复。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM