Dancing Links & Algorithm X
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的更多相关文章
- Dancing Links and Exact Cover
1. Exact Cover Problem DLX是用来解决精确覆盖问题行之有效的算法. 在讲解DLX之前,我们先了解一下什么是精确覆盖问题(Exact Cover Problem)? 1.1 Po ...
- ZOJ 3209 Treasure Map (Dancing Links)
Treasure Map Time Limit: 2 Seconds Memory Limit: 32768 KB Your boss once had got many copies of ...
- HUST 1017 - Exact cover (Dancing Links 模板题)
1017 - Exact cover 时间限制:15秒 内存限制:128兆 自定评测 5584 次提交 2975 次通过 题目描述 There is an N*M matrix with only 0 ...
- POJ 3074 Sudoku (Dancing Links)
传送门:http://poj.org/problem?id=3074 DLX 数独的9*9的模板题. 具体建模详见下面这篇论文.其中9*9的数独怎么转化到精确覆盖问题,以及相关矩阵行列的定义都在下文中 ...
- HDU5046 Airport dancing links 重复覆盖+二分
这一道题和HDU2295是一样 是一个dancing links重复覆盖解决最小支配集的问题 在给定长度下求一个最小支配集,只要小于k就行 然后就是二分答案,每次求最小支配集 只不过HDU2295是浮 ...
- HDU 3335 Divisibility dancing links 重复覆盖
分析: dlx重复覆盖的巧用,重复覆盖的原理恰好符合本题的筛选方式,即选择一个数后,该数的倍数或约数可以保证在之后的搜索中不会被选择 于是修改一下启发函数,求解最大的重复覆盖即可. 其实不一定不被 ...
- HDU 2295 Radar dancing links 重复覆盖
就是dancing links 求最小支配集,重复覆盖 精确覆盖时:每次缓存数据的时候,既删除行又删除列(这里的删除列,只是删除表头) 重复覆盖的时候:只删除列,因为可以重复覆盖 然后重复覆盖有一个估 ...
- POJ 3076 Sudoku (dancing links)
题目大意: 16*16的数独. 思路分析: 多说无益. 想说的就是dancing links 的行是依照 第一行第一列填 1 第一行第二列填 2 -- 第一行第十五列填15 第一行第二列填 1 -- ...
- Dancing Links 学习笔记
Dancing Links 本周的AI引论作业布置了一道数独 加了奇怪剪枝仍然TLE的Candy?不得不去学了dlx dlxnb! Exact cover 设全集X,X的若干子集的集合为S.精确覆盖是 ...
随机推荐
- Google V8编程详解(一)V8的编译安装(Ubuntu)
V8的编译比较简单,需要同时安装git和svn. 下载V8源码: git clone git://github.com/v8/v8.git v8 && cd v8 切换到最新版本: g ...
- linux 驱动学习笔记04--简单驱动
首先贴代码helloworld.c和Makefile /************************************************************************ ...
- (转)IC验证概述
验证是确保设计和预定的设计期望一致的过程,设计期望通常是通过设计规范来定义的.对于芯片设计,在不同的阶段可以分为:寄存器传输级(RTL)的功能验证.门级的仿真验证.形式验证以及时序验证.我们通常所说的 ...
- 使用WebClient 或者 HttpWebRequest均报:"The Remote name can't be solved"
错误原因: 未配置代理服务器设置的问题, 需要在配置节做如下操作. ============================================ 文章编号: 318140 - 查看本文应用 ...
- BIRT报表工具,直接导出EXCEL
BIRT是一款基于JAVA的免费开源报表工具,使用起来也挺方便. 有时你可能不需要在浏览器中展示报表,然后在点击导出按钮保存为EXCEL, 这里提供一种方式,直接把报表导出为EXCEL下载. JS代码 ...
- nodejs require
The rules of where require finds the files can be a little complex, but a simple rule of thumb is th ...
- U-Mail邮件系统六项特色服务铸就金口碑
评价一款邮件系统优劣的标准或许有很多,左右你是否选择某个平台的需求或许有不同,但是U-Mail小编必须提醒你:服务水准不可等闲视之!之所以如此, 这是因为:现代社会垃圾邮件猖獗,病毒层出不穷令人防不胜 ...
- XML数据 JSON数据 LitJSON 数据 的编写和解析 小结
用XML生成如下数据<?xml version="1.0"encoding="UTF-8"?><Transform name="My ...
- iphone 开源汇总(转)
原文地址 http://blog.csdn.net/devday/article/details/6105793 扫描wifi信息: http://code.google.com/p/uwecaugm ...
- limux curl命令
linux curl命令很强大: http://blog.chinaunix.net/uid-14735472-id-3413867.html curl是一种命令行工具,作用是发出网络请求,然后得到和 ...