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. EntityFramework+MySql 笔记1

    最近需要使用mysql ,而之前用惯了EF,所以就尝试EntityFramework+MySql的方案. 首先上网搜了一大通资料后,这样开始: 安装mysql,我用的版本是5.6.25 ( windo ...

  2. Python遍历目录下所有文件的最后一行进行判断若错误及时邮件报警-案例

    遍历目录下所有文件的最后一行进行判断若错误及时邮件报警-案例: #-*- encoding: utf-8 -*- __author__ = 'liudong' import linecache,sys ...

  3. 大毕设-matlab-AM调制解调

    博主大毕设关于数字下变频(DDC)的CUDA实现,预计工期比较长,所以留下一些文字记录. 主要分为两部分工作,Matlab仿真部分和CUDA实现. 由于很久没有仿真了,所以先用一个简单的AM调制仿真练 ...

  4. machine leanring 笔记 octave命令笔记

    来源于coursea 的公开课 A*B 一般意义的矩阵相乘 A.*B矩阵各位相乘 A.^2 A矩阵的每个数平方 1./A  对A矩阵的各位取倒 .表示对每一项都如此操作 log (A) exp(A) ...

  5. YII2学习第一天

    YII2学习第一天,之前稍微看了看TP,感觉和自己的理念不是很符合,然后转学YII2了. 使用的文档是https://github.com/yiisoft/yii2/tree/master/docs/ ...

  6. vim 标记 mark 详解 (转载)

    http://www.cnblogs.com/jianyungsun/archive/2011/02/14/1954057.html Vim 允许你在文本中放置自定义的标记.命令 "ma&q ...

  7. R常见的几种常见统计图

    1,向日葵散点图 2,热图  (颜色越深,数值越大) 3,折线图(散点图),绘制散点图集用 paris(data.frame)

  8. mysql的约束类型

    1.主键约束 2.非空约束 3.唯一性约束 4.外键约束 5.默认值约束

  9. UVM的类库

    [转]http://www.asicdv.com/ 一个UVM验证平台可以看成由多个模块组合在一起的,这和以前的verilog代码,以及verilog结合其它各种语言的验证手段在理念上是一样的,最大的 ...

  10. 转载 --ios 模型-setValuesForKeysWithDictionary

    应用场景:app请求后端数据,返回的数据是JSON形式,如: { "is_favor" = 0; "is_follow" = 0; "is_prais ...