精确覆盖问题:在一个0-1矩阵中,选定部分行,使得每一列都有且只有一个1。求解一种选法

舞蹈链(Dance Link),也就是一个循环十字链表,可以快速的删掉和恢复某行某列

结合了舞蹈链的搜索就称作DLX算法

这里贴一个用DLX算法解决16×16数独的代码

9×9的直接暴力会更好

 // LA2659 Sudoku
// Rujia Liu
#include<cstdio>
#include<cstring>
#include<vector> using namespace std; const int maxr = ;
const int maxn = ;
const int maxnode = ; // 行编号从1开始,列编号为1~n,结点0是表头结点; 结点1~n是各列顶部的虚拟结点
struct DLX {
int n, sz; // 列数,结点总数
int S[maxn]; // 各列结点数 int row[maxnode], col[maxnode]; // 各结点行列编号
int L[maxnode], R[maxnode], U[maxnode], D[maxnode]; // 十字链表 int ansd, ans[maxr]; // 解 void init(int n) { // n是列数
this->n = n; // 虚拟结点
for(int i = ; i <= n; i++) {
U[i] = i; D[i] = i; L[i] = i-, R[i] = i+;
}
R[n] = ; L[] = n; sz = n + ;
memset(S, , sizeof(S));
} void addRow(int r, vector<int> columns) {
int first = sz;
for(int i = ; i < columns.size(); i++) {
int c = columns[i];
L[sz] = sz - ; R[sz] = sz + ; D[sz] = c; U[sz] = U[c];
D[U[c]] = sz; U[c] = sz;
row[sz] = r; col[sz] = c;
S[c]++; sz++;
}
R[sz - ] = first; L[first] = sz - ;
} // 顺着链表A,遍历除s外的其他元素
#define FOR(i,A,s) for(int i = A[s]; i != s; i = A[i]) void remove(int c) {
L[R[c]] = L[c];
R[L[c]] = R[c];
FOR(i,D,c)
FOR(j,R,i) { U[D[j]] = U[j]; D[U[j]] = D[j]; --S[col[j]]; }
} void restore(int c) {
FOR(i,U,c)
FOR(j,L,i) { ++S[col[j]]; U[D[j]] = j; D[U[j]] = j; }
L[R[c]] = c;
R[L[c]] = c;
} // d为递归深度
bool dfs(int d) {
if (R[] == ) { // 找到解
ansd = d; // 记录解的长度
return true;
} // 找S最小的列c
int c = R[]; // 第一个未删除的列
FOR(i,R,) if(S[i] < S[c]) c = i; remove(c); // 删除第c列
FOR(i,D,c) { // 用结点i所在行覆盖第c列
ans[d] = row[i];
FOR(j,R,i) remove(col[j]); // 删除结点i所在行能覆盖的所有其他列
if(dfs(d+)) return true;
FOR(j,L,i) restore(col[j]); // 恢复结点i所在行能覆盖的所有其他列
}
restore(c); // 恢复第c列 return false;
} bool solve(vector<int>& v) {
v.clear();
if(!dfs()) return false;
for(int i = ; i < ansd; i++) v.push_back(ans[i]);
return true;
} }; ////////////// 题目相关
#include<cassert> DLX solver; const int SLOT = ;
const int ROW = ;
const int COL = ;
const int SUB = ; // 行/列的统一编解码函数。从1开始编号
int encode(int a, int b, int c) {
return a*+b*+c+;
} void decode(int code, int& a, int& b, int& c) {
code--;
c = code%; code /= ;
b = code%; code /= ;
a = code;
} char puzzle[][]; bool read() {
for(int i = ; i < ; i++)
if(scanf("%s", puzzle[i]) != ) return false;
return true;
} int main() {
int kase = ;
while(read()) {
if(++kase != ) printf("\n");
solver.init();
for(int r = ; r < ; r++)
for(int c = ; c < ; c++)
for(int v = ; v < ; v++)
if(puzzle[r][c] == '-' || puzzle[r][c] == 'A'+v) {
vector<int> columns;
columns.push_back(encode(SLOT, r, c));
columns.push_back(encode(ROW, r, v));
columns.push_back(encode(COL, c, v));
columns.push_back(encode(SUB, (r/)*+c/, v));
solver.addRow(encode(r, c, v), columns);
} vector<int> ans;
assert(solver.solve(ans)); for(int i = ; i < ans.size(); i++) {
int r, c, v;
decode(ans[i], r, c, v);
puzzle[r][c] = 'A'+v;
}
for(int i = ; i < ; i++)
printf("%s\n", puzzle[i]);
}
return ;
}

搜索:DLX算法的更多相关文章

  1. [蘑菇街] 搜索、算法团队招募牛人啦-年底了走过路过不要错过 - V2EX

    [蘑菇街] 搜索.算法团队招募牛人啦-年底了走过路过不要错过 - V2EX [蘑菇街] 搜索.算法团队招募牛人啦-年底了走过路过不要错过

  2. 关于用舞蹈链DLX算法求解数独的解析

    欢迎访问——该文出处-博客园-zhouzhendong 去博客园看该文章--传送门 描述 在做DLX算法题中,经常会做到数独类型的题目,那么,如何求解数独类型的题目?其实,学了数独的构建方法,那么DL ...

  3. 【DLX算法】hdu3498 whosyourdaddy

    题意:给你一个01矩阵,让你选择尽可能少的行数,使得这些行的并集能够覆盖到所有列. DLX算法求解重复覆盖问题模板,使用估价函数进行剪枝. #include<cstdio> #includ ...

  4. 【DLX算法】poj2676 Sudoku

    DLX算法求解精确覆盖问题模板.赛场上可以参见白书. #include<cstdio> #include<cstring> #include<vector> usi ...

  5. Python排序搜索基本算法之归并排序实例分析

    Python排序搜索基本算法之归并排序实例分析 本文实例讲述了Python排序搜索基本算法之归并排序.分享给大家供大家参考,具体如下: 归并排序最令人兴奋的特点是:不论输入是什么样的,它对N个元素的序 ...

  6. 搜索相关性算法在 DiDi Food 中的搜索

    导读:今天给大家分享的主题是搜索匹配问题在 DiDi Food 中的一些探索与应用.本文首先介绍了搜索相关性的一些背景,之后介绍了业界常见的三种匹配模型,以及在DiDi Food业务中的模型效果对比. ...

  7. 图的遍历(搜索)算法(深度优先算法DFS和广度优先算法BFS)

    图的遍历的定义: 从图的某个顶点出发访问遍图中所有顶点,且每个顶点仅被访问一次.(连通图与非连通图) 深度优先遍历(DFS): 1.访问指定的起始顶点: 2.若当前访问的顶点的邻接顶点有未被访问的,则 ...

  8. 广度优先搜索 BFS算法

    广度优先搜索算法(Breadth-First-Search,BFS),又称作宽度优先搜索.BFS算法是从根节点开始,沿着树的宽度遍历树的节点.如果所有节点均被访问,则算法中止. 算法思想 1.首先将根 ...

  9. DLX算法一览

    目录: 1 X思想的了解. 链表的递归与回溯. 具体操作. 优化. 一些应用与应用中的再次优化(例题). 练手题 X思想的了解. 首先了解DLX是什么? DLX是一种多元未饱和型指令集结构,DLX 代 ...

随机推荐

  1. android入门 — Service

    Service完全在后台运行,没有用户界面.使用的时候先创建Service子类,然后在AndroidManifest.xml中进行注册,同时可以通过<intent-filter.../>进 ...

  2. Solr初步研究

    Solr是一个高性能,采用Java5开发,Solr基于Lucene的全文搜索服务器.同时对其进行了扩展,提供了比Lucene更为丰富的查询语言,同时实现了可配置.可扩展并对查询性能进行了优化,并且提供 ...

  3. CodeForces Round #527 (Div3) C. Prefixes and Suffixes

    http://codeforces.com/contest/1092/problem/C Ivan wants to play a game with you. He picked some stri ...

  4. Windows连接Linux服务器中MySQL数据库-权限配置

    问题描述 在Windows系统中安装了监控MySQL数据库服务器性能的工具Spotlight on MySQL,利用Spotlight连接Linux服务器中的MySQL,进行相关配置如下:   点击& ...

  5. Tomcat安装及配置详解

    Tomcat安装及配置详解   一,Tomcat简介 Tomcat 服务器是一个免费的开放源代码的Web 应用服务器,Tomcat是Apache 软件基金会(Apache Software Found ...

  6. Html5新增元素中Canvas 与内联SVG的比较!

    SVG与Canvas的区别与比较如下: svg:使用xml描述2D图形,canvas使用javascript描述2D图形. Canvas 是逐像素进行渲染的,在 canvas 中,一旦图形被绘制完成, ...

  7. Java 调用 google 翻译

    1.Java代码 public class Translator { public String translate(String langFrom, String langTo, String wo ...

  8. 使用 Maven 管理项目

    最近的练手项目使用的是 Maven 在管理项目,在使用 Maven 管理项目时,三层的开发时分模块开发的,parent-dao-service-web,所有的spring+struts + Hiber ...

  9. Delphi下使用指针的简单总结

    由于最近公司太忙,好久没有更新我的BLOG了.原来想着写写关于HOOK驱动的文章,可是最后想想好久已经没有做驱动的东西了,怕写出来有错误,于是作罢.开发游戏也有一段时间了,发现使用DELPHI来开发网 ...

  10. bzoj2013[CEOI2010] A huge tower

    题意 有N(2<=N<=620000)快砖,要搭一个N层的塔,要求:如果砖A恰好在砖B上面,那么A不能比B的长度+D要长.问有几种方法,输出 答案 mod 1000000009的值 分析 ...