我在使用递归回溯算法解决C语言中的数据时遇到问题

时间:2014-03-05 03:18:32

标签: c sudoku backtracking solver recursive-backtracking

我可以解决一个简单的谜题,但尝试稍微更难的谜题是不可能的;我在俯瞰什么?这是我的解算器方法:

   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网格中......我很丢失,因为它似乎对我来说是正确的,但它太慢了。谢谢你的帮助!

1 个答案:

答案 0 :(得分:0)

您的实施需要额外的检查。

当找到当前(x, y)的当前有效候选者时,从棋盘开头找到下一个未确定的位置是多余的。

递归函数的复杂度为O(N*N)*O(N)*M(N是棋盘的边长,或者9.M是checkEverything的复杂度。)在此表达式中,{{1} }是找到下一个未确定的位置,O(N*N)是尝试从1到N的每个数字的复杂性。我不知道你如何实现O(N),但是一个天真的工具将是{{1} }。这意味着总复杂度可能约为O(N 4

优化的常见建议是:

  1. 降低了找到下一个职位的复杂性checkEverything。您可以预先处理棋盘并提前将所有未确定的位置放入列表中。

  2. 降低M = O(N)的复杂性。它可以通过使用一些哈希表来保存已使用的数字,每列9个,每行9个,每个子矩形9个,可以缩减为O(1)

  3. 有了这两个建议,递归的复杂性将是checkEverything

    如果你想要一个完美的表演,我建议你学习Knuth发明的Dancing Links。该算法的主要思想是使用二维双链表来存储所有位置的所有候选者并加速寻找下一个位置和下一个候选者,删除无效候选者并在回溯时恢复。

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