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. Winform 五种常用对话框控件的简单使用

    OpenFileDialog(打开文件对话框)FolderBrowserDialog(浏览文件夹对话框)SaveFileDialog(保存文件对话框)ColorDialog(颜色选择对话框)FontD ...

  2. win10无法使用内置管理员账户打开应用怎么办

    HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System \UIPI 右边有个默认的项.将它的值改成1

  3. js原生方法传参的细节(面试必问)

    废话不说,直接上题. slice(),接收两个参数,第一个为开始index(从0开始),第二个为结束的index(也是从0开始,但是不包括index本身,只到index-1).返回值是截取的数组,原数 ...

  4. LAMP环境

    LAMP =  Linux + Apache + MySQL + PHP    [1]     [2]      [3]     [4] [1]Linux是一套免费使用和自由传播的类Unix操作系统, ...

  5. Netty

    首先值得注意的是netty的jar包版本问题,版本不同,运用的方式也不同.我这里用4.0版本. 对于小白来说,netty到底是什么,我就没必要在这里阐明了,因为百度上比我描述的更全面. 这里就直接开门 ...

  6. iOS开发中多线程间关于锁的使用

    为什么需要使用锁,当然熟悉多线程的你,自然不会感到陌生. 那你在代码中是否很好的使用了锁的机制呢?你又知道几种实现锁的方法呢? main.m 1 int main(int argc, const ch ...

  7. 循序渐进Python3(十一) --3--  web之dom

    DOM                  文档对象模型(Document Object Model,DOM)是一种用于HTML和XML文档的编程接口.它给文档提供了一种结构化的表示方法,可以改变文档的 ...

  8. css3、html5学习笔记

    2016/12/14 ----认真看完绝对对你有帮助 HTML5针对移动端,移动端的浏览器主要是chrome,是webkit内核; app(applicatin):应用; native app:原生的 ...

  9. [知识整理]Java集合(一) - List

    一.实现List的几个类: ArrayList.LinkedList.CopyOnWriteArrayList.Vector 二.几个List底层的数据结构: ArrayList - 数组列表 Lin ...

  10. 利用Service bus中的queue中转消息

    有需求就有对策就有市场. 由于公司global的policy,导致对公司外发邮件的service必须要绑定到固定的ip地址,所以别的程序需要调用发邮件程序时,问题就来了,如何在azure上跨servi ...