通过Backtracking的Sudoku Solver无法正常工作

时间:2009-10-06 03:48:21

标签: algorithm sudoku backtracking

假设一个二维数组持有9x9数独网格,我的求解函数在哪里崩溃?我试图用一种简单的回溯方法来解决这个问题。谢谢!

bool solve(int grid[9][9])
{
 int i,j,k;
 bool isSolved = false;

  if(!isSolved(grid))
   isSolved = false;

  if(isSolved)
   return isSolved;

  for(i=0; i<9; i++)
  {
   for(j=0; j<9; j++)
   {
    if(grid[i][j] == 0)
    {
     for(k=1; k<=9; k++)
     {
      if(legalMove(grid,i,j,k))
      {
       grid[i][j] = k;
       isSolved = solve(grid);
       if (isSolved)
        return true;
      }
      grid[i][j] = 0;
     }
     isSolved = false;
    }
   }
  }

return isSolved;
}

即使在更改isSolved问题之后,我的解决方案似乎也会分解为无限循环。看起来我错过了一些基础案例步骤,但我不确定在哪里或为什么。我看过类似的解决方案,仍然无法确定问题。我只是想创建基本求解器,不需要追求效率。谢谢你的帮助!

3 个答案:

答案 0 :(得分:4)

是你的基本情况搞砸了。在递归函数中,应该在开始时处理基本情况。你有

bool isSolved = false;

if(!isSolved(grid))
    isSolved = false;

if(isSolved)
    return isSolved;

请注意,您的isSolved变量永远不能设置为true,因此您的代码

if(isSolved)
    return isSolved;

无关紧要。

即使你解决这个问题,它也会感觉像是一个无限循环,即使它是有限的。这是因为您的算法每次调用求解时总共可以检查9 * 9 * 9 = 729个案例。输入此功能n次可能需要检查多达729 ^ n个案例。它不会明显地检查那么多案例,因为当安置是非法的时候它会找到死胡同,但是可以说90%的可能数字的存在会导致除一个数字之外的所有数字合法合适的情况?此外,即使你要检查平均k个案例,其中k是一个小数字(k <= 10),这仍然会爆炸(运行时间为k ^ n。)

诀窍是“尝试”将数字放置在可能导致实际良好位置的高概率的位置。可能我想到的最简单的方法是约束满足求解器,或带启发式的搜索算法(如A *。)

我实际上是根据约束满足求解器编写了一个数独求解器,它可以在不到一秒的时间内解决100x100的sudokus。

如果通过一些奇迹,“强力”回溯算法在9x9情况下适合您,尝试更高的值,您将很快看到运行时间的恶化。

我不是在抨击回溯算法,事实上我喜欢它,它已经一次又一次地显示回溯如果正确实现可以像动态编程一样有效,但是,在你的情况下你没有实现它正确。你正在强制它,你可能只是让你的代码非递归,它将完成同样的事情。

答案 1 :(得分:3)

您将 isSolved 称为函数和布尔变量。 我不认为这是合法的,它绝对不聪明。

您的函数应具有与变量不同的名称。

答案 2 :(得分:2)

似乎无论是否合法移动,您都将“0”分配给方格,其中“grid [i] [j] = 0;”线。也许你打算把“else”和那么“grid [i] [j] = 0;” ?