繁体   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