数独生成算法实现

来源:互联网 发布:淘宝卖家的钱在哪儿看 编辑:程序博客网 时间:2024/04/30 16:42

  • 整体设计实现
  • 局部推演实现
    • 宫局部推演实现
    • 行局部推演实现
    • 列局部推演实现
  • 单个数字实现
  • 随机数推演


整体设计实现

找出一个最基本的初始值,借用单个数字按顺序排列来实现:

每个数字,按照从1~9行,1~9列,1~9格放置

数字1:

0 1 2 3 4 5 6 7 8 9 1 1 2 1 3 1 4 1 5 1 6 1 7 1 8 1 9 1

数字2:

0 1 2 3 4 5 6 7 8 9 1 2 2 2 3 2 4 2 5 2 6 2 7 2 8 2 9 2

同理3~9,组合成初始值:

0 1 2 3 4 5 6 7 8 9 1 1 2 3 4 5 6 7 8 9 2 7 8 9 1 2 3 4 5 6 3 4 5 6 7 8 9 1 2 3 4 9 1 2 3 4 5 6 7 8 5 6 7 8 9 1 2 3 4 5 6 3 4 5 6 7 8 9 1 2 7 8 9 1 2 3 4 5 6 7 8 5 6 7 8 9 1 2 3 4 9 2 3 4 5 6 7 8 9 1

我们来总结一下这规律:
- 前置条件
矩阵左上角坐标 0,0,称为零点坐标
矩阵九宫格按先横后竖向划分为9个3行3列的区域,称为1~9宫,以宫为单位划分新的坐标 Gx,Gy,0 <= Gx,Gy <= 2


  • 规律

对于某一个数字 n,其第一次(最贴近零点坐标)出现的坐标为 (x,y),其所在宫的坐标为 (Gx,gy),(Gx,Gy) 与 (x,y) 有如下转换规则:Gx = x/3, Gy = y/3
对于某一个数字 n,其坐标为(x,y),其所在宫的坐标为 (Gx,Gy),其所在宫的范围有如下转换规则:Gx*3 <= x <= Gx*3+2,Gy*3 <= y <= Gy*3+2
完全逆序排列的结果与完全正序排列的结果在数值上对称,即1~4对应9~6,5的位置不变,由此可以得到终止值:

0 1 2 3 4 5 6 7 8 9 1 9 8 7 6 5 4 3 2 1 2 3 2 1 9 8 7 6 5 4 3 6 5 4 3 2 1 9 8 7 4 1 9 8 7 6 5 4 3 2 5 4 3 2 1 9 8 7 6 5 6 7 6 5 4 3 2 1 9 8 7 2 1 9 8 7 6 5 4 3 8 5 4 3 2 1 9 8 7 6 9 8 7 6 5 4 3 2 1 9

局部推演实现

宫局部推演实现

一个宫有 9! = 40320 种排序方式,也就是说每次从40320种宫中不放回地选择一个宫,直到9个宫满足所有条件。

这里为了减少计算量,可以再将宫按照某一个数字分为9种类型,一种类型只取一个,每种类型有 5040 种宫。但这里无法再递归定义,因为一个数字与数字是几又是不同的考虑维度。

行局部推演实现

同宫局部推演,一行有 9! = 40320 种排序方式,也就是说每次从40320种行中不放回地选择一行,直到9行满足所有条件。

列局部推演实现

同行局部推演。

单个数字实现

会玩数独的朋友应该都知道数独中1~9这九个数字之间的位置其实是没有直接关联的,借用局部推演的概念,我们把局部推演的单位换成以数字为单位。

先推算出所有1的位置,然后是所有2的位置,……
这样子从所有1的位置中选择一种,在所有2的位置中选择一种,……
满足所有条件就行了……

条件:
当前数字为 n,当前数字所在宫、行、列中没有 n,下一个数字为 n+1,下一个数字的所有分布与当前数字位置上不重复

假设我们来推算所有1的位置的排列可能性:

第一个1:81种不解释

第二个1:行列以及1所在宫中不能重复含有1,则有 (9-3)*(9-1)+(9-1)*(9-3)-(9-3)*(9-3) = 60

1 2 3 4 5 6 7 8 9 1 1 0 0 0 0 0 0 0 2 0 0 0 3 0 0 0 4 0 5 0 6 0 7 0 8 0 9 0

第三个1:取决于第二个1是有重复的排,还是无重复的排

无重复的排第二个1:

0 1 2 3 4 5 6 7 8 9 1 1 0 0 0 0 0 0 0 0 2 0 0 0 0 3 0 0 0 0 4 0 0 0 1 0 0 0 0 0 5 0 0 0 0 6 0 0 0 0 7 0 0 8 0 0 9 0 0

无重复的排第二个1,有(9-3-1)*(3-1)+(3-1)*(9-3-1)+(9-6)*(9-3-1)+(9-6)*(9-3-1)+(9-6)*(9-6) = 41

有重复的排第二个1:

0 1 2 3 4 5 6 7 8 9 1 1 0 0 0 0 0 0 0 0 2 0 0 0 1 0 0 0 0 0 3 0 0 0 0 0 0 4 0 0 5 0 0 6 0 0 7 0 0 8 0 0 9 0 0

有重复的排第二个1,有(9-3)*(9-2)+(9-6)*(3-2) = 45

为了便于计算,均采取有重复的排第方式,那么就换算成底下的矩阵加上三宫可用的部分

(9-3)*(9-2)+(9-6)*(3-2) = 45

第四个1:有(9-3)*(9-3)+(9-9)*(3-3) = 36

0 1 2 3 4 5 6 7 8 9 1 1 0 0 0 0 0 0 0 0 2 0 0 0 1 0 0 0 0 0 3 0 0 0 0 0 0 1 0 0 4 0 0 0 5 0 0 0 6 0 0 0 7 0 0 0 8 0 0 0 9 0 0 0

第五个1:有(9-6)*(9-4)+(9-3-2)*(3-1) = 25

0 1 2 3 4 5 6 7 8 9 1 1 0 0 0 0 0 0 0 0 2 0 0 0 1 0 0 0 0 0 3 0 0 0 0 0 0 1 0 0 4 0 1 0 0 0 0 0 0 0 5 0 0 0 0 0 6 0 0 0 0 0 7 0 0 0 0 8 0 0 0 0 9 0 0 0 0

第六个1:有(9-6)*(9-5)+(9-6-1)*(3-2) = 14

0 1 2 3 4 5 6 7 8 9 1 1 0 0 0 0 0 0 0 0 2 0 0 0 1 0 0 0 0 0 3 0 0 0 0 0 0 1 0 0 4 0 1 0 0 0 0 0 0 0 5 0 0 0 0 1 0 0 0 0 6 0 0 0 0 0 0 0 7 0 0 0 0 0 8 0 0 0 0 0 9 0 0 0 0 0

第七个1:有(9-9)*(9-6)+(9-6)*(3-0) = 9

0 1 2 3 4 5 6 7 8 9 1 1 0 0 0 0 0 0 0 0 2 0 0 0 1 0 0 0 0 0 3 0 0 0 0 0 0 1 0 0 4 0 1 0 0 0 0 0 0 0 5 0 0 0 0 1 0 0 0 0 6 0 0 0 0 0 0 0 1 0 7 0 0 0 0 0 0 8 0 0 0 0 0 0 9 0 0 0 0 0 0

第八个1:有(9-9)*(9-7)+(9-7)*(3-1) = 4

0 1 2 3 4 5 6 7 8 9 1 1 0 0 0 0 0 0 0 0 2 0 0 0 1 0 0 0 0 0 3 0 0 0 0 0 0 1 0 0 4 0 1 0 0 0 0 0 0 0 5 0 0 0 0 1 0 0 0 0 6 0 0 0 0 0 0 0 1 0 7 0 0 1 0 0 1 0 0 1 8 0 0 0 0 0 0 0 9 0 0 0 0 0 0 0

第九个1:有(9-3)*(9-8)+(9-8)*(3-2) = 1

0 1 2 3 4 5 6 7 8 9 1 1 0 0 0 0 0 0 0 0 2 0 0 0 1 0 0 0 0 0 3 0 0 0 0 0 0 1 0 0 4 0 1 0 0 0 0 0 0 0 5 0 0 0 0 1 0 0 0 0 6 0 0 0 0 0 0 0 1 0 7 0 0 1 0 0 0 0 0 0 8 0 0 0 0 0 1 0 0 0 9 0 0 0 0 0 0 0 0

随机数推演

查了一下数独一共有多少种情况之后,觉得很可惜,单凭排列组合这种方法基本是没办法生成的。除非可以将所有排列的可能性推算出来,但那个计算量也不容小觑。(参考全排列算法)

这个方法借用了以上几种方法的结论,按照数字1~9开始设计,比如,难度调为 n,n 难度中一共给出 min~max 个数字,这 min~max 个数字中,平均每个数字分配几个?或者按照每个宫分配几个,或者每个行分配几个,然后以某个随机值作为偏移量,总数达到 m,min <= m <= max。

然后设计一个计算量较小的求解过程,尽快得出一个完整的矩阵即可。


CSDN 辣鸡 MD 编辑器,无序列表格式全丢

原创粉丝点击