数独的游戏要求在一个9X9的格子内填入1~9的数字,使得每一行,每一列,以及九个3X3的子区域内都没有重复的数字。如何用程序的方法来解这个问题呢?
稍作思索,我写出了第一种解法。从事后查询维基百科1来看,这种方法可以称之为回溯法。思路很简单,依次扫描每一个待填数字的空格:
1. 在第一个空格里面填上“1”,检查这个数字是否合法(其所在的行、列,以及3X3的子区域里不存在重复的数字)。如果合法,则前进到第二个格子。否则,在这个格子里继续试2,3,… ,直到合法为止。
2. 在第二个格子里面继续填数字,从“1”开始试起,直到找到一个合法的数字,继续进到下一格。
3. 如果在某个格子里,从“1”到“9”都不合法,这说明前面某个格子填错了。这时就回退到上一格,从还没试的数字里面继续试。例如,如果上一格已填的数字是3,就继续试4,5,6,… 是否合法。如果找到一个合法的数字,则又前进到下一格。如果找不到,说明前面还有格子也填错了,则继续回退到更前面一格,… 如此反复。
4. 如果这个数独是有解的,我们总会遇到“每个格子都碰巧填对了”的情况。如果这个数独是没有解的,那么我们会遇到“第一个格子试了1~9所有的数字都不行”的情况。
用C++实现了一下2。求解上面的例子很快,基本上是秒杀。
按理到这儿就结束了。不过,看上去这个解法只能给出数独的一个解,有没有什么方法能够求出某个数独的所有解呢?
数独的游戏就是往9X9个格子里填入1~9的数字,那么一共有9X9X9 … X9 = 981 种排列组合的情况。如果把81个格子摊平,写成一个81位长的数字,那么从0 0 0 0 0 … 0 到 9 9 9 9 9 … 9 就穷尽了所有的情况。但是显然,我们不可能去验证这所有981种情况。目前Intel i7处理器每秒约可执行2.38 X 1011条指令3,即使我们的程序只有981条指令,它也无法在我们的有生之年算出结果。
有没有办法减少待验证的解的数目呢?第一个想法是我们只需要排列组合空格子里的数字,那么对于