经过查阅资料,目前的数独终局生成方法大体分为回溯法在线生成 和 根据种子数独变换得到。数独的解题方法主要分为 回溯法和 基于规则的方法。
数独终局生成
回溯法
https://medium.com/@rossharrison/generating-sudoku-boards-pt-1-structures-algorithms-a1e62feeb32
没什么好说的,从坐上到右下依次填合法的数字,失败就回退。
这个链接主要是使用各种STL库改进了效率的问题。
回溯法可以通过每次选数填入的随机性来做到随机生成数独,这是变换法不能做到的。
回溯法有多种改进方法:
- 一次填一个数字 一般可以避免过早进入死胡同
- 先随机填写中心的宫,稍微减少一些问题规模再回溯(我在想随机填写对角线三个宫是否能保证有解,不过目前还没有想法)
变换法
找到种子数独,然后使用各种变换制造新的数独
- 1~9数字的置换
- 旋转0,90,180,270角度
- 正反面翻转
- 同宫的行列交换
这种办法比回溯法速度要快。
数独解题算法
回溯法
没什么好说的,相当于生成算法从已经有结果的状态开始运行。
基于规则的方法
搜索StackOverflow,这个norvig的方法貌似非常火爆。而且直觉上比回溯法可能更有效率一些,因为它基于规则进行剪枝。
简而言之,每个格子有一些备选数字的集合,求解的操作就是根据删除规则(基于人的推理过程)其中的元素直到只剩下一个确定解为止。
删除元素的时候是递归操作的,删除操作的影响可能使其他格子也满足删除条件:
(1) If a square has only one possible value, then eliminate that value from the square's peers.
(2) If a unit has only one possible place for a value, then put the value there.
这个过程叫Constraint Propagation。
当删无可删的时候,进行深度优先搜索。但是因为深搜的同时也用规则,所以对原局面破坏的很严重,于是作者放弃回溯的“保护现场”,而选择为每个分支直接复制一份盘面使用。
其他参考资料:
http://www.cnblogs.com/kaige/p/sudok_algorithms.html
https://blog.csdn.net/Xcodingman/article/details/80639788
https://blog.csdn.net/qq_26822029/article/details/81129701
https://blog.csdn.net/nibiewuxuanze/article/details/47679927