Dancing Links 模板
struct dl{
// x: line, y: column
struct node{
int c, left, right, up, down;
};
vector<node> a;
using vec = vector<int>;
using mat = vector<vec>;
vec cnt;
// 构造十字交叉循环链表有多种写法
// 1.流行的模板: link(int r, int c),每次添加一个元素。另外需要个数组row[],存储每一行中某个元素(可以是这一行中的任意元素,不必是最后一次添加的那个元素)的位置。
// 2.每次传入0-1矩阵中某一行的列编号数组
// 3.每次传入0-1矩阵的所有元素(我的实现即如此)
// 行列都从1开始编号,若不需要求答案则node中不用记录行编号
// m:0-1矩阵的列数
void build(const mat &b, int m){
a.clear();
cnt = vec(m+1);
for(int i=0; i<=m; i++)
a.push_back({i, (i+m)%(m+1), (i+1)%(m+1), i, i});
for(auto &i: b)
for(auto &j: i){
node cur={j, -1, -1, a[j].up, j};
a[cur.up].down=a.size();
a[cur.down].up=a.size();
if(j==i.front())
cur.left=cur.right=a.size();
else{
cur.left=a.size()-1;
cur.right=a.back().right;
a[cur.right].left=a.size();
a[cur.left].right=a.size();
}
a.push_back(cur);
++cnt[j];
}
}
// to cover some column
// no overhead!
void cover(int col){
// 删除第 col 列
a[a[col].right].left=a[col].left;
a[a[col].left].right=a[col].right;
// cnt[col]=0 // no need to do so.
// 删除所有在第 col 列有元素的行
for(int i=a[col].down; i!=col; i=a[i].down){
for(int j=a[i].right; j!=i; j=a[j].right){
a[a[j].up].down=a[j].down;
a[a[j].down].up=a[j].up;
// assert(a[j].y != col);
--cnt[a[j].c];
}
}
}
// to uncover some column
void uncover(int col){
// 恢复第 col 列
a[a[col].left].right=col;
a[a[col].right].left=col;
// 恢复所有在第 col 列有元素的行
for(int i=a[col].down; i!=col; i=a[i].down){
for(int j=a[i].right; j!=i; j=a[j].right){
a[a[j].up].down=j;
a[a[j].down].up=j;
++cnt[a[j].c];
}
}
}
void dance(int & res, int lev){
if(lev>=res) return; // 剪枝
int mi = INT_MAX, c=0;
for(int i=a[0].right; i; i=a[i].right)
if(cnt[i] < mi){
mi = cnt[i];
c = i;
}
if(c==0){
res=lev;
return;
};
// a[i].y == i holds.
cover(c);
// 枚举在第 i 列有元素的行
for(int i=a[c].down; i!=c; i=a[i].down){
// to choose some line
// res.push_back(a[i].x);
for(int j=a[i].right; j!=i; j=a[j].right){ // 覆盖在第 i 行有元素的列
cover(a[j].c);
}
// if(dance(res)) return true;
dance(res, lev+1);
// res.pop_back();
for(int j=a[i].left; j!=i; j=a[j].left){
uncover(a[j].c);
}
}
uncover(c);
return;
}
// constructor
};
Dancing Links 的原理可以参考 hihoCoder Week #101 和 Donold Knuth 的论文。
Dancing Links 的实现,网上的模板大都是 Knuth 论文里的伪代码风格: L[], R[], U[], D[], C[]四个数组。 构造双向十字循环链表的方法是定义 void link(int r, int c) 函数,每个插入一个元素(0-1矩阵中的某个1)。我认为这种写法是比较好的,简洁又灵活。我的实现与常见的写法略有不同,其差别无关紧要。
实现要点
- 若不要求输出具体方案,则无需存储每个元素的列。若需要输出具体方案,则往往涉及从0-1矩阵的行编号到对应的决策的解码(decode)操作。
- 选择0-1矩阵的某一行这一操作对应到对双向十字循环链表的操作中即“覆盖”(
cover())这一行所能覆盖的那些列。 - 根据具体题目修改
dance()函数。
Dancing Links 模板的更多相关文章
- HUST 1017 - Exact cover (Dancing Links 模板题)
1017 - Exact cover 时间限制:15秒 内存限制:128兆 自定评测 5584 次提交 2975 次通过 题目描述 There is an N*M matrix with only 0 ...
- ZOJ 3209 Treasure Map (Dancing Links)
Treasure Map Time Limit: 2 Seconds Memory Limit: 32768 KB Your boss once had got many copies of ...
- HUST1017(KB3-A Dancing links)
1017 - Exact cover Time Limit: 15s Memory Limit: 128MB Special Judge Submissions: 7270 Solved: 3754 ...
- [ACM] HUST 1017 Exact cover (Dancing Links,DLX模板题)
DESCRIPTION There is an N*M matrix with only 0s and 1s, (1 <= N,M <= 1000). An exact cover is ...
- hust 1017 dancing links 精确覆盖模板题
最基础的dancing links的精确覆盖题目 #include <iostream> #include <cstring> #include <cstdio> ...
- Dancing Links and Exact Cover
1. Exact Cover Problem DLX是用来解决精确覆盖问题行之有效的算法. 在讲解DLX之前,我们先了解一下什么是精确覆盖问题(Exact Cover Problem)? 1.1 Po ...
- Dancing Links初学记
记得原来备战OI的时候,WCX大神就研究过Dancing Links算法并写了一篇blog.后来我还写了个搜索策略的小文章( http://www.cnblogs.com/pdev/p/3952279 ...
- POJ 3074 Sudoku (Dancing Links)
传送门:http://poj.org/problem?id=3074 DLX 数独的9*9的模板题. 具体建模详见下面这篇论文.其中9*9的数独怎么转化到精确覆盖问题,以及相关矩阵行列的定义都在下文中 ...
- poj 3074 Sudoku(Dancing Links)
Sudoku Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 8152 Accepted: 2862 Descriptio ...
随机推荐
- ES6, Angular,React和ABAP中的String Template(字符串模板)
String Template(字符串模板)在很多编程语言和框架中都支持,是一个很有用的特性.本文将Jerry工作中使用到的String Template的特性做一个总结. ES6 阮一峰老师有一个专 ...
- iOS 微信和支付宝关于回调处理
在支付这一块,发现讲支付集成的比较多,但是关于支付后回调处理的不多见,(当时因为这个问题懵逼了好久)就自己总结一下, 1.支付宝回调 支付宝的回调想对来说比较简单一些,因为支付宝的回调就在调起支付宝的 ...
- python基础一 day15 复习
迭代器和生成器迭代器 可迭代协议 —— 含有iter方法的都是可迭代的 迭代器协议 —— 含有next和iter的都是迭代器 特点 节省内存空间 方便逐个取值,一个迭代器只能取一次.生成器 —— 迭代 ...
- 生成gt数据出问题
使用cout打印uchar类型数据时,打印出来是其相应的ascii码
- python实现单链表翻转
题目描述: 翻转一个链表 您在真实的面试中是否遇到过这个题? Yes 样例 给出一个链表1->2->3->null,这个翻转后的链表为3->2->1->null 挑 ...
- on() 和 click() 的区别
on() 和 click() 的区别: 二者在绑定静态控件时没有区别,但是如果面对动态产生的控件,只有 on() 能成功的绑定到动态控件中. 以下实例中原先的 HTML 元素点击其身后的 Delete ...
- PostgreSQL学习(2)-- mvcc
1.PG事务隔离级别 在数据库中,并发的操作进行读写数据时,则会遇到脏读.不可重复读.幻读.串行化异常等问题. 数据库事务的特性: 原子性(Atomicity):事务作为一个整体被执行,包含在其中的对 ...
- docker镜像下载
获得CentOS的Docker CE 预计阅读时间: 10分钟 要在CentOS上开始使用Docker CE,请确保 满足先决条件,然后 安装Docker. 先决条件 Docker EE客户 要安装D ...
- Applied Nonparametric Statistics-lec2
Ref: https://onlinecourses.science.psu.edu/stat464/print/book/export/html/3 The Binomial Distributio ...
- STM32F407VET6之IAR之ewarm7.80.4工程建立(基于官方固件库1.6版本)
今天把stm32F407的工程之IAR建立完成了,特此记录下. 下载官方固件库,STM32F4xx_DSP_StdPeriph_Lib_V1.6.1,V1.8.0版本的同理.新建以下几个文件 src放 ...