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. Google V8编程详解(一)V8的编译安装(Ubuntu)

    V8的编译比较简单,需要同时安装git和svn. 下载V8源码: git clone git://github.com/v8/v8.git v8 && cd v8 切换到最新版本: g ...

  2. linux 驱动学习笔记04--简单驱动

    首先贴代码helloworld.c和Makefile /************************************************************************ ...

  3. (转)IC验证概述

    验证是确保设计和预定的设计期望一致的过程,设计期望通常是通过设计规范来定义的.对于芯片设计,在不同的阶段可以分为:寄存器传输级(RTL)的功能验证.门级的仿真验证.形式验证以及时序验证.我们通常所说的 ...

  4. 使用WebClient 或者 HttpWebRequest均报:"The Remote name can't be solved"

    错误原因: 未配置代理服务器设置的问题, 需要在配置节做如下操作. ============================================ 文章编号: 318140 - 查看本文应用 ...

  5. BIRT报表工具,直接导出EXCEL

    BIRT是一款基于JAVA的免费开源报表工具,使用起来也挺方便. 有时你可能不需要在浏览器中展示报表,然后在点击导出按钮保存为EXCEL, 这里提供一种方式,直接把报表导出为EXCEL下载. JS代码 ...

  6. nodejs require

    The rules of where require finds the files can be a little complex, but a simple rule of thumb is th ...

  7. U-Mail邮件系统六项特色服务铸就金口碑

    评价一款邮件系统优劣的标准或许有很多,左右你是否选择某个平台的需求或许有不同,但是U-Mail小编必须提醒你:服务水准不可等闲视之!之所以如此, 这是因为:现代社会垃圾邮件猖獗,病毒层出不穷令人防不胜 ...

  8. XML数据 JSON数据 LitJSON 数据 的编写和解析 小结

    用XML生成如下数据<?xml version="1.0"encoding="UTF-8"?><Transform name="My ...

  9. iphone 开源汇总(转)

    原文地址 http://blog.csdn.net/devday/article/details/6105793 扫描wifi信息: http://code.google.com/p/uwecaugm ...

  10. limux curl命令

    linux curl命令很强大: http://blog.chinaunix.net/uid-14735472-id-3413867.html curl是一种命令行工具,作用是发出网络请求,然后得到和 ...