DLX算法求解数独

原创 2018年04月16日 20:40:57
首先,DLX算法并不是为了解数独而提出的,它是为了解决精确覆盖问题而被提出的。
精确覆盖问题:给定一个由0-1组成的矩阵,是否能找到一个行的集合,使得集合中每一列都恰好包含一个1。
数独这个问题恰好拟合了DLX算法的模型,所以可以用该方法求解。
DLX算法的具体分析请看跳跃的舞者,舞蹈链(Dancing Links)算法——求解精确覆盖问题。该帖讲述的十分详细,就不在这里赘述算法的本身了。DLX算法实质上是一种解决问题的模型,它是一种通用的搜索方法,只需要进行适当的转化与建模,就能将一个复杂问题转化为精确覆盖问题。再配合上双向十字链表的优化,大大降低递归成本。
在上面的精确覆盖问题中,我们可以分析得到两个要点:1.要求每列都被覆盖;2.恰好包含一个1,也就是说要恰好每列都被一个1覆盖,也就是“有且只有一个”。所以在分析问题的时候,我们可以将行可以看做是我们可以选择的解空间,而列则是该解空间所要满足的要求。
比如说数独,对于数独的DLX构造,先来分析行。对于数独的每个格子,都有9种填法,所以最后有9*81=729种,DLX的行就是729行。而对于列,首先,对于数独的81个格子,每个格子都只能填一个数,所以需要81列来保证每个格子中有且只有一个数;其次,对于数独的每一行,都需要满足有且恰好只有一个1,有且恰好只有一个2,……,有且恰好只有一个9,所以每一行都需要9列,9行就需要81列;同理,列与九宫格与行所要满足的要求是一样的。所以最后一共需要81*4=324列来满足数独的题目要求。在上述所有列的分析中,需要满足的条件都是“有且只有一个”,这与前面的覆盖问题恰好吻合。
对于DLX数组的列坐标分配:
0~80列——格
81~161列——行
162~242列——列
243~323列——九宫格
所以设row为行坐标,col为列坐标,num=9 * row + col,则在数独中
1.对于每个未知的点来说:
for (int i = 0; i < 9; i++)
{
Matrix[num * 9 + i][num] = 1;//每格唯一
Matrix[num * 9 + i][81 + row * 9 + i] = 1;//每行每个数唯一
Matrix[num * 9 + i][162 + col * 9 + i] = 1;//每行每个数唯一
Matrix[num * 9 + i][243 + (row / 3 * 3 + col / 3) * 9 + i] = 1;
//每九宫格每个数唯一
}
对于一个未知的点,它能填9个数,所以将所有的需求都添加进去;
2.对于一个已知的点来说:
{
i = sudoku[row][col] - '1';//得到该数
Matrix[num * 9 + i][num] = 1;//每格唯一
Matrix[num * 9 + i][81 + row * 9 + i] = 1;//每行每个数唯一
Matrix[num * 9 + i][162 + col * 9 + i] = 1;//每行每个数唯一
Matrix[num * 9 + i][243 + (row / 3 * 3 + col / 3) * 9 + i] = 1;
//每九宫格每个数唯一
}

对于一个已知的点,它的num列是唯一的,所以为了满足要求,在搜索过程中,它是一定会被选中的,这样就保证了该点的选择的唯一性。

在后续过程中,则需要建立一个双向十字链表,然后进行DFS。过程很繁琐,就不在这里赘述了。

上述就是对数独问题用DLX算法进行求解的建模了。可以发现,如果一个问题可以用DLX求解,那么只要通过适当的建模,就可以把任何复杂的问题转化为一个已知解法的搜索问题。而在建模的时候,抓住“有且只有一个”这一重要条件,就可以轻松理解问题,并加以转化。

关闭计算机就这几招

 关闭计算机就这几招注:完全翻译整理自MSDN。非常简单. Vcbear.“系统ShutDown”属于Windows系统的一种基本服务。功能上有“关闭系统”,“注销用户”,“锁定工作站”3中操作。SD...
  • vcbear
  • vcbear
  • 2002-01-11 09:40:00
  • 1502

舞蹈链算法与数独求解

舞蹈链算法与数独求解 舞蹈链算法 舞蹈链算法用于求解精确覆盖问题 。 精确覆盖问题可以理解为如下问题: 给定一个01矩阵,寻找一个行的集合,使得集合中的列恰好满足每一列包含一个1。...
  • xiahn1a
  • xiahn1a
  • 2016-03-11 21:36:41
  • 2274

DLX算法及应用(一)DLX模板+解数独

DLX算法 原理:网上太多了,我就不写了。。 用途:解决精确覆盖问题 下面的代码是严格按照算法写的,其实对于这种没有数据域的链表,是可以用数组进行模拟的(见DLX算法及应用(二)Matlab解数独)。...
  • u012453913
  • u012453913
  • 2014-01-06 16:02:16
  • 2310

DLX算法求解精确覆盖问题

在网上看到一篇非常好的介绍舞蹈链的文章,转载之。 1.原文链接:点击打开链接 2.跳跃的舞者,舞蹈链(Dancing Links)算法——求解精确覆盖问题 精确覆盖问题的定义:给定一个由0-...
  • u014800748
  • u014800748
  • 2015-08-12 08:44:58
  • 1346

DLX算法介绍

在介绍DLX算法前,先说下X算法,通过比较才 知道DLX算法的好。 X算法是一种常规的回溯算法,我们可以用一个递归过程求精确覆盖问题。 递归过程描述为:选择一个没有被删除的列,然后枚举该列为1的行,将...
  • wuli2496
  • wuli2496
  • 2015-01-23 22:14:16
  • 5126

DLX算法合集 I

DLX是一种相当神奇的数据结构,通常用于解决矩阵(多为稀疏矩阵)的 重复|精确 覆盖的问题。不过一般这类问题的难点是抽出转化关系,剩下的几乎就是套模板...
  • solotzg
  • solotzg
  • 2015-02-22 12:42:32
  • 453

(模板)dlx 精确覆盖和重复覆盖

精确覆盖 #define mxn 1120 #define N 1000200 int n, m, t, size; int U[N], D[N], L[N], R[N], C[N], Row[N...
  • u013654696
  • u013654696
  • 2014-10-15 11:26:05
  • 762

【算法】Dancing Links (DLX) II

1. 应用 在前一篇中,简要地介绍了DLX算法,这篇将主要讲DLX的应用。DLX是用来解决extract cover问题的,有一些问题如果能转化成extract cover问题,也就意味着能用DL...
  • lifehack
  • lifehack
  • 2013-10-27 15:54:07
  • 1742

【精确覆盖问题】DLX算法

数独问题最优算法 // 行编号从1开始,列编号为1~n,结点0是表头结点; 结点1~n是各列顶部的虚拟结点 struct DLX { int n, sz; // 列数,结点总数 int...
  • u012837895
  • u012837895
  • 2014-05-12 21:25:15
  • 459

DLX题集

FZU 1686 神龙的难题 HDU1426  Sudoku Killer HDU1530 Maximum Clique  HDU1603 A Puzzling Proble...
  • yew1eb
  • yew1eb
  • 2014-04-08 09:11:59
  • 1848
收藏助手
不良信息举报
您举报文章:DLX算法求解数独
举报原因:
原因补充:

(最多只允许输入30个字)