舞蹈链(Dancing Links)算法求解数独

利用舞蹈链(Dancing Links)算法求解数独问题,实际上就是下面一个流程

1、把数独问题转换为精确覆盖问题

2、设计出数据矩阵

3、用舞蹈链(Dancing Links)算法求解该精确覆盖问题

4、把该精确覆盖问题的解转换为数独的解

 

首先看看数独问题(9*9的方格)的规则

1、每个格子只能填一个数字

2、每行每个数字只能填一遍

3、每列每个数字只能填一遍

4、每宫每个数字只能填一遍(宫的概念,参看“算法实践——数独的基本解法”)

 

那现在就是利用这个规则把数独问题转换为精确覆盖问题

可是,直观上面的规则,发现比较难以转换为精确覆盖问题。因此,把上面的表述换个说法

1、每个格子只能填一个数字

2、每行1-9的这9个数字都得填一遍(也就意味着每个数字只能填一遍)

3、每列1-9的这9个数字都得填一遍

4、每宫1-9的这9个数字都得填一遍

 

这样理解的话,数独问题转换为精确覆盖问题就相对简单多了。关键就是如何构造精确覆盖问题中的矩阵

 

我们把矩阵的每个列都定义成一个约束条件。

 

第1列定义成:(1,1)填了一个数字

第2列定义成:(1,2)填了一个数字

……

第9列定义成:(1,9)填了一个数字

第10列定义成:(2,1)填了一个数字

……

第18列定义成:(2,9)填了一个数字

……

第81列定义成:(9,9)填了一个数字

至此,用第1-81列完成了约束条件1:每个格子只能填一个数字

第N列(1≤N≤81)定义成:(X,Y)填了一个数字。

N、X、Y之间的关系是:X=INT((N-1)/9)+1;Y=((N-1) Mod 9)+1;N=(X-1)×9+Y

 

 

第82列定义成:在第1行填了数字1

第83列定义成:在第1行填了数字2

……

第90列定义成:在第1行填了数字9

第91列定义成:在第2行填了数字1

……

第99列定义成:在第2行填了数字9

……

第162列定义成:在第9行填了数字9

至此,用第82-162列(共81列)完成了约束条件2:每行1-9的这9个数字都得填一遍

第N列(82≤N≤162)定义成:在第X行填了数字Y。

N、X、Y之间的关系是:X=INT((N-81-1)/9)+1;Y=((N-81-1) Mod 9)+1;N=(X-1)×9+Y+81

 

 

第163列定义成:在第1列填了数字1

第164列定义成:在第1列填了数字2

……

第171列定义成:在第1列填了数字9

第172列定义成:在第2列填了数字1

……

第180列定义成:在第2列填了数字9

……

第243列定义成:在第9列填了数字9

至此,用第163-243列(共81列)完成了约束条件3:每列1-9的这9个数字都得填一遍

第N列(163≤N≤243)定义成:在第X列填了数字Y。

N、X、Y之间的关系是:X=INT((N-162-1)/9)+1;Y=((N-162-1) Mod 9)+1;N=(X-1)×9+Y+162

 

 

第244列定义成:在第1宫填了数字1

第245列定义成:在第1宫填了数字2

……

第252列定义成:在第1宫填了数字9

第253列定义成:在第2宫填了数字1

……

第261列定义成:在第2宫填了数字9

……

第324列定义成:在第9宫填了数字9

至此,用第244-324列(共81列)完成了约束条件4:每宫1-9的这9个数字都得填一遍

第N列(244≤N≤324)定义成:在第X宫填了数字Y。

N、X、Y之间的关系是:X=INT((N-243-1)/9)+1;Y=((N-243-1) Mod 9)+1;N=(X-1)×9+Y+243

 

至此,用了324列完成了数独的四个约束条件,矩阵的列定义完成

那接下来,就是把数独转换为矩阵

数独问题中,每个格子分两种情况。有数字的格子、没数字的格子。

 

有数字的格子

以例子来说明,在(4,2)中填的是7

把(4,2)中填的是7,解释成4个约束条件

1、在(4,2)中填了一个数字。

2、在第4行填了数字7

3、在第2列填了数字7

4、在第4宫填了数字7(坐标(X,Y)到宫N的公式为:N=INT((X-1)/3)×3+INT((Y-1)/3)+1)

 

那么这4个条件,分别转换成矩阵对应的列为

1、在(4,2)中填了一个数字。对应的列N=(4-1)×9+2=29

2、在第4行填了数字7。对应的列N=(4-1)×9+7+81=115

3、在第2列填了数字7。对应的列N=(2-1)×9+7+162=178

4、在第4宫填了数字7。对应的列N=(4-1)×9+7+243=277

 

于是,(4,2)中填的是7,转成矩阵的一行就是,第29、115、178、277列是1,其余列是0。把这1行插入到矩阵中去。

 

没数字的格子

还是举例说明,在(5,8)中没有数字

把(5,8)中没有数字转换成

(5,8)中填的是1,转成矩阵的一行就是,第44、118、226、289列是1,其余列是0。

(5,8)中填的是2,转成矩阵的一行就是,第44、119、227、290列是1,其余列是0。

(5,8)中填的是3,转成矩阵的一行就是,第44、120、228、291列是1,其余列是0。

(5,8)中填的是4,转成矩阵的一行就是,第44、121、229、292列是1,其余列是0。

(5,8)中填的是5,转成矩阵的一行就是,第44、122、230、293列是1,其余列是0。

(5,8)中填的是6,转成矩阵的一行就是,第44、123、231、294列是1,其余列是0。

(5,8)中填的是7,转成矩阵的一行就是,第44、124、232、295列是1,其余列是0。

(5,8)中填的是8,转成矩阵的一行就是,第44、125、233、296列是1,其余列是0。

(5,8)中填的是9,转成矩阵的一行就是,第44、126、234、297列是1,其余列是0。

把这9行插入到矩阵中。由于这9行的第44列都是1(不会有其他行的44列会是1),也就是说这9行中必只有1行(有且只有1行)选中(精确覆盖问题的定义,每列只能有1个1),是最后解的一部分。这就保证了最后解在(5,8)中只有1个数字。

 

这样,从数独的格子依次转换成行(1行或者9行)插入到矩阵中。完成了数独问题到精确覆盖问题的转换。

接下来求解精确覆盖问题就交给舞蹈链(Dancing Links)算法,详情参看

  • 5
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值