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 模板的更多相关文章

  1. HUST 1017 - Exact cover (Dancing Links 模板题)

    1017 - Exact cover 时间限制:15秒 内存限制:128兆 自定评测 5584 次提交 2975 次通过 题目描述 There is an N*M matrix with only 0 ...

  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. HUST1017(KB3-A Dancing links)

    1017 - Exact cover Time Limit: 15s Memory Limit: 128MB Special Judge Submissions: 7270 Solved: 3754 ...

  4. [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 ...

  5. hust 1017 dancing links 精确覆盖模板题

    最基础的dancing links的精确覆盖题目 #include <iostream> #include <cstring> #include <cstdio> ...

  6. Dancing Links and Exact Cover

    1. Exact Cover Problem DLX是用来解决精确覆盖问题行之有效的算法. 在讲解DLX之前,我们先了解一下什么是精确覆盖问题(Exact Cover Problem)? 1.1 Po ...

  7. Dancing Links初学记

    记得原来备战OI的时候,WCX大神就研究过Dancing Links算法并写了一篇blog.后来我还写了个搜索策略的小文章( http://www.cnblogs.com/pdev/p/3952279 ...

  8. POJ 3074 Sudoku (Dancing Links)

    传送门:http://poj.org/problem?id=3074 DLX 数独的9*9的模板题. 具体建模详见下面这篇论文.其中9*9的数独怎么转化到精确覆盖问题,以及相关矩阵行列的定义都在下文中 ...

  9. poj 3074 Sudoku(Dancing Links)

    Sudoku Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 8152   Accepted: 2862 Descriptio ...

随机推荐

  1. [转]maven项目部署到tomcat

    其实maven项目部署到tomcat的方式很多,我从一开始的打war包到tomcat/webapps目录,到使用tomcat-maven插件,到直接使用servers部署,一路来走过很多弯路. 下面就 ...

  2. [VC]在VC++中实现让程序只运行一个实例的方法且实现该实例

    方法一: 有时候在开发应用程序时,希望控制程序运行唯一的实例.例如,最常用的mp3播放软 件Winamp,由于它需要独占计算机中的音频设备,因此该程序只允许自身运行唯一的一个例程.在Visual C+ ...

  3. 在CNN中使用Tensorflow进行数据增强

    开始之前,需要思考一些基本问题 1.为什么需要大量数据 当您训练机器学习模型时,您真正在做的是调整其参数,以便它可以将特定输入(例如,图像)映射到某个输出(标签).我们的优化目标是追逐我们模型损失较低 ...

  4. centos7-httpd虚拟主机

    Apache虚拟主机: 一台WEB服务器发布单个网站会非常浪费资源,所以一台WEB服务器上会发布多个网站, 在一台服务器上发布多网站,也称之为部署多个虚拟主机,WEB虚拟主机配置方法有三种: 基于单I ...

  5. C++ Stack 与String

    // ConsoleApplication1.cpp : 此文件包含 "main" 函数.程序执行将在此处开始并结束. // #include "pch.h" ...

  6. iOS JS 交互之利用系统JSContext实现 JS调用oc方法

    ios js 交互分为两块: 1.oc调用js 这一块实现起来比较简单, 我的项目中加载的是本地的html,js,css,需要注意的是当你向工程中拖入这些文件时,选择如下操作,(拖入的文件夹是蓝色的, ...

  7. git 指令记录

    由于之前一直用svn 用git也是用图形化的工具 还是要了解一下git指令 因为都是版本控制工具 有很多相似之处 所以理解起来也比较轻松 仓库: github上面的项目 工作目录下面的所有文件都不外乎 ...

  8. pandas处理大文本数据

    当数据文件是百万级数据时,设置chunksize来分批次处理数据 案例:美国总统竞选时的数据分析 读取数据 import numpy as np import pandas as pdfrom pan ...

  9. destoon 数据库操作

    1.插入数据 $db->query("INSERT INTO ".get_table($mid)." ($sqlk) VALUES ($sqlv)");  ...

  10. LeetCode(44) Wildcard Matching

    题目 Implement wildcard pattern matching with support for '?' and '*'. '?' Matches any single characte ...