1 参考链接

   http://www.cnblogs.com/steady/archive/2011/03/15/1984791.html#undefined

   http://en.wikipedia.org/wiki/Dancing_Links

2 双向链表

  可用数组实现

  删除x操作

  Function Remove

    x.left.right <-x.right

    x.right.left <- x.left

  恢复x

  Function Resume

    x.left.right <- x

    x.right.left <- x

3 精确覆盖(Exact Cover Problem)

  给定一个01矩阵, 现在要选择一些行,使得每一列有且仅有一个1

  解决办法:搜索

4 数独转化

  数独满足的条件:

    1. 每个格子都填有数字

    2. 每一行都要有1~9这9个数字填入

    3. 每一列都要有1~9这9个数字填入

    4. 每一坨都要有1~9这9个数字填入  

  可构造一个729*324的由01构成的矩阵

     //i,j,k表示在棋盘上i行j列填入数字k

    行:

      1到81,表示棋盘中9*9=81个格子是否填入了数字。如果是,则选取的01行在该01列上有1

        对应的01列编号为:(i-1)*9+j

      

      81+1到81*2,表示棋盘中9行,每行的9个不同的数字是否填入。棋盘上某行已经填入了某个数字,则在选取的01行上,对应的01列有1。

        对应的01列编号为:81+(i-1)*9+k。

      

      81*2+1到81*3,表示棋盘中9列,每列的9个不同的数字是否填入。

        对应的01列编号为:81*2+(j-1)*9+k。

      

      81*3+1到81*4,表示棋盘中9块,每块的9个不同的数字是否填入。

      01行是状态。数独做完后的状态是什么,就是棋盘上每个格子填入的究竟是什么数字

      所以,01行表示的是,棋盘上某个格子填入的是什么数字。

      那01行的行数就是9*9*9。

5 Sample

vijos 1345 数独大赛

 #include <cstdio>
#include <cstring> const int MAXA = ;
const int MAXC = +;
const int MAXR = +;
const int MAXN = MAXR*+MAXC; int n = , T; struct DancingLinks{
char c;
int sz, S[MAXC],
Col[MAXN], Row[MAXN],
L[MAXN], R[MAXN], U[MAXN], D[MAXN],
head[MAXA][MAXA][MAXA],
anna[MAXA][MAXA]; inline void Clear(){
memset(S, , sizeof(S));
memset(Col, , sizeof(Col));
for (int i=; i<=*; i++)
L[i] = i-, R[i] = i+,
U[i] = i, D[i] = i;
L[] = n, R[n] = ;
sz = n;
} inline void Scan(){
do
c = getchar();
while (!(<=c && c<=)); for (int i=; i<=; i++)
for (int j=; j<=; j++)
anna[i][j] = c-,
c = getchar();
} inline void Print(){
for (int i=; i<=; i++)
for (int j=; j<=; j++)
printf("%d", anna[i][j]);
printf("\n");
} inline int _GetPortion(int i,int j){
return (--i/)*+(--j/+);
} inline void AddNode(int c,int sz){
U[D[c]] = sz, D[sz] = D[c];
U[sz] = c, D[c] = sz;
S[c] ++, Col[sz] = c;
} inline void Remove(int c){
L[R[c]] = L[c], R[L[c]] = R[c];
for (int i=D[c]; i!=c; i=D[i])
for (int j=R[i]; j!=i; j=R[j])
U[D[j]]=U[j], D[U[j]]=D[j],
-- S[Col[j]];
} inline void Resume(int c){
for (int i=U[c]; i!=c; i=U[i])
for (int j=L[i]; j!=i; j=L[j])
U[D[j]] = j, D[U[j]] = j,
++ S[Col[j]];
L[R[c]] = c, R[L[c]] = c;
} inline bool DFS(int k){
if (k>) return true; int c = R[], temp;
for (int i=R[]; i!=; i=R[i]){
if (!S[i]) return false;
if (S[i]<S[c]) c = i;
}
Remove(c); for (int i=D[c]; i!=c; i=D[i]){
temp = Row[i];
anna[temp/][(temp/)%] = temp%;
for (int j=R[i]; j!=i; j=R[j])
Remove(Col[j]); if (DFS(k+)) return true; for (int j=L[i]; j!=i; j=L[j])
Resume(Col[j]);
}
Resume(c); return false;
} inline void AddRow(int i, int j, int k){
for (int u=; u<=; u++)
L[sz+u] = sz+u-, R[sz+u] = sz+u+,
Row[sz+u] = *i+*j+k; L[sz+] = sz+, R[sz+] = sz+;
head[i][j][k] = sz+;
AddNode(*+(i-)*+j, ++sz);
AddNode(*+(i-)*+k, ++sz);
AddNode(*+(j-)*+k, ++sz);
AddNode(*+(_GetPortion(i,j)-)*+k, ++sz);
} inline void EatCarrot(){
Clear();
Scan(); for (int i=; i<=; i++)
for (int j=; j<=; j++)
if (anna[i][j]) AddRow(i, j, anna[i][j]);
else
for (int k=;k<=;k++)
AddRow(i, j, k); int k = ;
for (int i=; i<=; i++)
for (int j=; j<=; j++)
if (anna[i][j]){
++ k;
Remove(Col[head[i][j][anna[i][j]]]);
for (int u=R[head[i][j][anna[i][j]]]; u!=head[i][j][anna[i][j]]; u=R[u])
Remove(Col[u]);
} DFS(k+);
Print();
}
}Rabbit; int main(){
scanf("%d", &T);
while (T--)
Rabbit.EatCarrot();
}

vijos 1345

wikioi 2924数独挑战

 #include <cstdio>
#include <cstring> const int MAXA = ;
const int MAXC = +;
const int MAXR = +;
const int MAXN = MAXR*+MAXC; int n = , T; struct DancingLinks{
int sz, S[MAXC],
Col[MAXN], Row[MAXN],
L[MAXN], R[MAXN], U[MAXN], D[MAXN],
head[MAXA][MAXA][MAXA],
anna[MAXA][MAXA]; inline void Clear(){
memset(S, , sizeof(S));
memset(Col, , sizeof(Col));
for (int i=; i<=*; i++)
L[i] = i-, R[i] = i+,
U[i] = i, D[i] = i;
L[] = n, R[n] = ;
sz = n;
} inline void Scan(){
for (int i=; i<=; i++)
for (int j=; j<=; j++)
scanf("%d", &anna[i][j]);
} inline void Print(){
for (int i=; i<=; i++){
for (int j=; j<=; j++)
printf("%d ", anna[i][j]);
printf("\n");
}
} inline int _GetPortion(int i,int j){
return (--i/)*+(--j/+);
} inline void AddNode(int c,int sz){
U[D[c]] = sz, D[sz] = D[c];
U[sz] = c, D[c] = sz;
S[c] ++, Col[sz] = c;
} inline void Remove(int c){
L[R[c]] = L[c], R[L[c]] = R[c];
for (int i=D[c]; i!=c; i=D[i])
for (int j=R[i]; j!=i; j=R[j])
U[D[j]]=U[j], D[U[j]]=D[j],
-- S[Col[j]];
} inline void Resume(int c){
for (int i=U[c]; i!=c; i=U[i])
for (int j=L[i]; j!=i; j=L[j])
U[D[j]] = j, D[U[j]] = j,
++ S[Col[j]];
L[R[c]] = c, R[L[c]] = c;
} inline bool DFS(int k){
if (k>) return true; int c = R[], temp;
for (int i=R[]; i!=; i=R[i]){
if (!S[i]) return false;
if (S[i]<S[c]) c = i;
}
Remove(c); for (int i=D[c]; i!=c; i=D[i]){
temp = Row[i];
anna[temp/][(temp/)%] = temp%;
for (int j=R[i]; j!=i; j=R[j])
Remove(Col[j]); if (DFS(k+)) return true; for (int j=L[i]; j!=i; j=L[j])
Resume(Col[j]);
}
Resume(c); return false;
} inline void AddRow(int i, int j, int k){
for (int u=; u<=; u++)
L[sz+u] = sz+u-, R[sz+u] = sz+u+,
Row[sz+u] = *i+*j+k; L[sz+] = sz+, R[sz+] = sz+;
head[i][j][k] = sz+;
AddNode(*+(i-)*+j, ++sz);
AddNode(*+(i-)*+k, ++sz);
AddNode(*+(j-)*+k, ++sz);
AddNode(*+(_GetPortion(i,j)-)*+k, ++sz);
} inline void EatCarrot(){
Clear();
Scan(); for (int i=; i<=; i++)
for (int j=; j<=; j++)
if (anna[i][j]) AddRow(i, j, anna[i][j]);
else
for (int k=;k<=;k++)
AddRow(i, j, k); int k = ;
for (int i=; i<=; i++)
for (int j=; j<=; j++)
if (anna[i][j]){
++ k;
Remove(Col[head[i][j][anna[i][j]]]);
for (int u=R[head[i][j][anna[i][j]]]; u!=head[i][j][anna[i][j]]; u=R[u])
Remove(Col[u]);
} DFS(k+);
Print();
}
}Rabbit; int main(){
Rabbit.EatCarrot();
}

wikioi 2924

Dancing Links & Algorithm X的更多相关文章

  1. Dancing Links and Exact Cover

    1. Exact Cover Problem DLX是用来解决精确覆盖问题行之有效的算法. 在讲解DLX之前,我们先了解一下什么是精确覆盖问题(Exact Cover Problem)? 1.1 Po ...

  2. ZOJ 3209 Treasure Map (Dancing Links)

    Treasure Map Time Limit: 2 Seconds      Memory Limit: 32768 KB Your boss once had got many copies of ...

  3. HUST 1017 - Exact cover (Dancing Links 模板题)

    1017 - Exact cover 时间限制:15秒 内存限制:128兆 自定评测 5584 次提交 2975 次通过 题目描述 There is an N*M matrix with only 0 ...

  4. POJ 3074 Sudoku (Dancing Links)

    传送门:http://poj.org/problem?id=3074 DLX 数独的9*9的模板题. 具体建模详见下面这篇论文.其中9*9的数独怎么转化到精确覆盖问题,以及相关矩阵行列的定义都在下文中 ...

  5. HDU5046 Airport dancing links 重复覆盖+二分

    这一道题和HDU2295是一样 是一个dancing links重复覆盖解决最小支配集的问题 在给定长度下求一个最小支配集,只要小于k就行 然后就是二分答案,每次求最小支配集 只不过HDU2295是浮 ...

  6. HDU 3335 Divisibility dancing links 重复覆盖

    分析: dlx重复覆盖的巧用,重复覆盖的原理恰好符合本题的筛选方式,即选择一个数后,该数的倍数或约数可以保证在之后的搜索中不会被选择 于是修改一下启发函数,求解最大的重复覆盖即可.   其实不一定不被 ...

  7. HDU 2295 Radar dancing links 重复覆盖

    就是dancing links 求最小支配集,重复覆盖 精确覆盖时:每次缓存数据的时候,既删除行又删除列(这里的删除列,只是删除表头) 重复覆盖的时候:只删除列,因为可以重复覆盖 然后重复覆盖有一个估 ...

  8. POJ 3076 Sudoku (dancing links)

    题目大意: 16*16的数独. 思路分析: 多说无益. 想说的就是dancing links 的行是依照 第一行第一列填 1 第一行第二列填 2 -- 第一行第十五列填15 第一行第二列填 1 -- ...

  9. Dancing Links 学习笔记

    Dancing Links 本周的AI引论作业布置了一道数独 加了奇怪剪枝仍然TLE的Candy?不得不去学了dlx dlxnb! Exact cover 设全集X,X的若干子集的集合为S.精确覆盖是 ...

随机推荐

  1. 数字信号处理--Z变换,傅里叶变换,拉普拉斯变换

    傅立叶变换.拉普拉斯变换.Z变换最全攻略 作者:时间:2015-07-19来源:网络       傅立叶变换.拉普拉斯变换.Z变换的联系?他们的本质和区别是什么?为什么要进行这些变换.研究的都是什么? ...

  2. <一>Angular.js学习

    angular.module(name, [a], [b]);  // angular.module()创建.获取.注册angular中的模块 name:字符串类型,代表模块的名称: a:字符串的数组 ...

  3. 有关于java反编译工具的使用

    有时候想去查看jar包中的class文件中的代码,但是class文件如果没有进行反编译操作的话,代码无法直观的查看.这时候可以使用jadeclipse对class文件进行反编译的操作. 1.首先这里需 ...

  4. [转载] 纯手打 第一篇:安装配置gradle

    本文转载自: http://www.cnblogs.com/uncle2000/p/4276833.html 一个bug 一个脚印的叫你们用gradle. 1介于网络上的很多资料都是老的 不适用与现在 ...

  5. Camstar Portal modeling user guid --自定义用户菜单

    通过studio 创建 menu definition 创建菜单 创建成功后到employee界面设置对应菜单就可以了

  6. HDU 4833 Best Financing (DP)

    Best Financing Time Limit: 20000/10000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) ...

  7. app 要求字体使用楷体,使用字体包

    1,下载字体包     http://www.3987.com/xiazai/6/fonts/36616.html#down 2.  studio中src\main\创建assets\fonts,存放 ...

  8. python中获取今天昨天和明天的日期

    import datetime today = datetime.date.today()oneday = datetime.timedelta(days=1)yesterday = today-on ...

  9. ArcEngine编辑保存错误:Unable to create logfile system tables

    通过ArcEngine对多个SDE中多个图层进行批量编辑处理,其中有部分图层在结束编辑的时候出现错误提示(部分图层可以,只有两个数据较多的图层保存失败). 错误信息:Unable to create ...

  10. WebStorm 8.0.1 注册码

    username:24718-12042010 key:00001h6wzKLpfo3gmjJ8xoTPw5mQvY YA8vwka9tH!vibaUKS4FIDIkUfy!!f 3C"rQ ...