DLX算法
原理:网上太多了,我就不写了。。
用途:解决精确覆盖问题
下面的代码是严格按照算法写的,其实对于这种没有数据域的链表,是可以用数组进行模拟的(见DLX算法及应用(二)Matlab解数独)。
代码中全部都用的是vector,更通用一些~
后半部分给出了一个解数独的实例,如何将数独转换为精确覆盖问题的文章也是网上一搜一大把。。。。我就不写了。。
2014-2-15 修改:还是写下如何转换吧
精确覆盖问题的矩阵表示:
给出这样一个矩阵,
1 0 0 1 0 0 1
1 0 0 1 0 0 0
0 0 0 1 1 0 1
0 0 1 0 1 1 0
0 1 1 0 0 1 1
0 1 0 0 0 0 1
找出该矩阵一组行的集合,使得该组集合中每列有且只有一个1
例如第2,4,6行
那么我们现在将数独问题转换成一个324列的精确覆盖问题:
数独有4个限制条件,将其分别转换为81列
每个格子都要填入数字
---1到81列,表示数独中9*9=81个格子是否填入了数字。如果是,则选取的01行在该01列上为1
每一行都要有1~9填入
---81+1到81*2列,每9列就代表数独中的一行,如果该行有某个数字,则其对应的列上为1
每一列都要有1~9填入
---81*2+1到81*3列,每9列就代表数独中的一列
每一宫都要有1~9填入
---81*3+1到81*4列,每9列就代表数独中的一宫
对于已给出数字的格子,例如第 3 行第 5 列为7
那么就插入一行,其中,第23,106,205,259列为1,其他为0,分别代表:
23 = (3-1)*9 + 5 第 3 行第 5 列填入了数字
106= 81 + (3-1)*9 + 7 第 3 行填入了7
205= 81*2 + (5-1)*9 + 7 第 5 列填入了7
259= 81*3 + (2-1)*9 + 7 第 2 宫填入了7
如果没有给出数字,那这个格子就有9种可能性,插入9行,其中如下列为1:
第一行:23,100,199,253
第二行:23,101,200,254
........
第九行:23,108,207,261
这样,构造的01矩阵,每行都有4个1。
在最多81*9行的01矩阵中,寻找一组精确覆盖(81行),就可以求解一个数独
代码如下
#include <time.h>
#include <iostream>
#include <limits.h>
#include <vector>
#include <fstream>
using namespace std;
struct Node{
Node *up, *down, *left, *right, *colRoot, *rowRoot;//上下左右四个指针以及指向行列对象的指针
int Num;//行对象特有,记录行数
int Size;//列对象特有,记录该列元素数
Node(int i = -1 ): Num(i),Size(0) {};//构造函数
};
class DLX{
public:
DLX(vector<vector<int> > &matrix, int m, int n);
~DLX