如果要自己手动解数独,我相信很多人都是会的,但是如何让电脑帮我们解数独呢?

最朴素的一个想法就是爆搜,但是爆搜的效率显然是很低的,我们要将问题进行转化再求解。

我们可以把数独的规则转化为4组条件:

1. 每行都要有1~9;

2. 每列都要有1~9;

3. 每个九宫格都要有1~9;

4. 每个格子都要填一个数。

这样一共要满足4×9×9 = 324个条件。

当我们填入一个数的时候,可以满足其中的4个条件,比如在(i, j)的位置上填入k,可以满足第i行有k、第j行有k、第(i/3)*3+(j/3)个九宫格中有k、第(i, j)这个格子中有数这4个条件。

填数的方法一共有9×9×9一共729种,我们需要从这729种填法中选出81种并且恰好能满足324个条件。

这样我们就将解数独转化成了一个精确覆盖问题。

我们可以用Dancing Links X(以下简称DLX)算法来解决精确覆盖问题。

DLX用一个十字循环链表维护了递归和回溯过程中的修改,大大提升了修改和回溯的效率,具体实现我就不再过多赘述。

下面给出我构造DLX的代码

 

for (int i = 0; i < 9; i++)
    for (int j = 0; j < 9; j++)
        for (int k = 0; k < 9; k++)
        {
            if (puzzle[i][j] != 0 && puzzle[i][j] != k + 1)
                continue;
            int r = encode(i, j, k);
            solver.link(r, encode(0, i, j));
            solver.link(r, encode(1, i, k));
            solver.link(r, encode(2, j, k));
            solver.link(r, encode(3, i / 3 * 3 + j / 3, k));
        }

 

经过DLX优化后,在我本机跑1000组数独大概1.5s,1e6组大概要跑25分钟,我觉得还是有提升空间的。

欢迎各位dalao指点。