数独—暴力求解算法
1.基本工作
数独是9×9的矩阵,为了代码清晰、使用方便,声明一个类进行封装
现在这个类简单的一个成员变量,一个构造函数还有一个接口函数。构造函数直接接受一个二维数组。
2.求解函数
我们的基本思路是按照人做数独题的方式去求解。
选择最优点 我们在做数独题的时候会大概看一遍整个9×9矩阵,选择一个周围数字比较多的点来,周围的数字越多,这个点上可排除的数字就越多,可能的情况是最少的。 我们就按照人的思路来,先遍历9×9矩阵,选择一个缺少的数字的数量最少的点,当做最优点,“猜”这个点上的数字。 定义一个选点函数:
这个选择最优的点的函数用到了另外三个函数
countLackNum(i,j)
、checkwin()
和attemptLocate(i,j)
。我们先继续按照思路走,这些函数先放着最后再写“猜”最优点上缺少的数字 首先需要确定这个这个点上缺少哪些数字,然后对这个点上可能的数字进行一个一个的试。我们首先想到的用一个固定的1-9数组,每当存在一个数字我们就从这个数组中删去这个数字,这个数组上需要的操作只有删除。如果删除数字时可以不用检查数组中是否包含这个数字,操作会方便很多。最后决定选择set作为容器,可以简单且快速的的进行删除 两个函数:
缺少的函数 至此主要矛盾已解决,上述代码将递归求解数独矩阵。 现在把上面缺少的函数
countLackNum(i,j)
和checkwin()
补充进去就可以运行了至此数据的求解已经完成,但还有一些地方需要补充
3.运行前错误检查
我们不能寄希望于用户提供的数字是完美的,相反,用户提供的数字常常可能伴着错误,比如直接在同一行里输入了两个1。如果带着这些错误运行,程序不卡死也会陷入巨大数量的循环中,几乎会对没有提供的数字集合进行一个遍历。假设用户提供了20个数字,其中有一行有两个1,那么程序会对剩下的71个点,每个点有n种(1< n< 9)可能,程序会进行n^71次计算,,最后返回一个0表示失败。这是一个不可能完成的任务。 所以我们需要提前检查错误,发现错误直接返回,不进入递归中。 定义一个函数
isBad()
用于运行前检查,同样选择set,可以快速插入,快速查找添加了错误处理,就要在代码中用到,我们的
beginCrack()
函数只在第一次调用,正是放置运行前错误处理的地方,beginCrack()
如下在使用的时候可根据
beginCrack()
的返回值不同,进行不同的错误处理。返回为0则正常运行。可以定义一个静态成员函数用来获取求解的结果4.代码实例
至此我们有了一个稳健的求解方法,下面是一个实例
瞬间完成,输出如下
Last updated
Was this helpful?