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

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

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

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

9×9的直接暴力会更好

  1. // LA2659 Sudoku
  2. // Rujia Liu
  3. #include<cstdio>
  4. #include<cstring>
  5. #include<vector>
  6.  
  7. using namespace std;
  8.  
  9. const int maxr = ;
  10. const int maxn = ;
  11. const int maxnode = ;
  12.  
  13. // 行编号从1开始,列编号为1~n,结点0是表头结点; 结点1~n是各列顶部的虚拟结点
  14. struct DLX {
  15. int n, sz; // 列数,结点总数
  16. int S[maxn]; // 各列结点数
  17.  
  18. int row[maxnode], col[maxnode]; // 各结点行列编号
  19. int L[maxnode], R[maxnode], U[maxnode], D[maxnode]; // 十字链表
  20.  
  21. int ansd, ans[maxr]; // 解
  22.  
  23. void init(int n) { // n是列数
  24. this->n = n;
  25.  
  26. // 虚拟结点
  27. for(int i = ; i <= n; i++) {
  28. U[i] = i; D[i] = i; L[i] = i-, R[i] = i+;
  29. }
  30. R[n] = ; L[] = n;
  31.  
  32. sz = n + ;
  33. memset(S, , sizeof(S));
  34. }
  35.  
  36. void addRow(int r, vector<int> columns) {
  37. int first = sz;
  38. for(int i = ; i < columns.size(); i++) {
  39. int c = columns[i];
  40. L[sz] = sz - ; R[sz] = sz + ; D[sz] = c; U[sz] = U[c];
  41. D[U[c]] = sz; U[c] = sz;
  42. row[sz] = r; col[sz] = c;
  43. S[c]++; sz++;
  44. }
  45. R[sz - ] = first; L[first] = sz - ;
  46. }
  47.  
  48. // 顺着链表A,遍历除s外的其他元素
  49. #define FOR(i,A,s) for(int i = A[s]; i != s; i = A[i])
  50.  
  51. void remove(int c) {
  52. L[R[c]] = L[c];
  53. R[L[c]] = R[c];
  54. FOR(i,D,c)
  55. FOR(j,R,i) { U[D[j]] = U[j]; D[U[j]] = D[j]; --S[col[j]]; }
  56. }
  57.  
  58. void restore(int c) {
  59. FOR(i,U,c)
  60. FOR(j,L,i) { ++S[col[j]]; U[D[j]] = j; D[U[j]] = j; }
  61. L[R[c]] = c;
  62. R[L[c]] = c;
  63. }
  64.  
  65. // d为递归深度
  66. bool dfs(int d) {
  67. if (R[] == ) { // 找到解
  68. ansd = d; // 记录解的长度
  69. return true;
  70. }
  71.  
  72. // 找S最小的列c
  73. int c = R[]; // 第一个未删除的列
  74. FOR(i,R,) if(S[i] < S[c]) c = i;
  75.  
  76. remove(c); // 删除第c列
  77. FOR(i,D,c) { // 用结点i所在行覆盖第c列
  78. ans[d] = row[i];
  79. FOR(j,R,i) remove(col[j]); // 删除结点i所在行能覆盖的所有其他列
  80. if(dfs(d+)) return true;
  81. FOR(j,L,i) restore(col[j]); // 恢复结点i所在行能覆盖的所有其他列
  82. }
  83. restore(c); // 恢复第c列
  84.  
  85. return false;
  86. }
  87.  
  88. bool solve(vector<int>& v) {
  89. v.clear();
  90. if(!dfs()) return false;
  91. for(int i = ; i < ansd; i++) v.push_back(ans[i]);
  92. return true;
  93. }
  94.  
  95. };
  96.  
  97. ////////////// 题目相关
  98. #include<cassert>
  99.  
  100. DLX solver;
  101.  
  102. const int SLOT = ;
  103. const int ROW = ;
  104. const int COL = ;
  105. const int SUB = ;
  106.  
  107. // 行/列的统一编解码函数。从1开始编号
  108. int encode(int a, int b, int c) {
  109. return a*+b*+c+;
  110. }
  111.  
  112. void decode(int code, int& a, int& b, int& c) {
  113. code--;
  114. c = code%; code /= ;
  115. b = code%; code /= ;
  116. a = code;
  117. }
  118.  
  119. char puzzle[][];
  120.  
  121. bool read() {
  122. for(int i = ; i < ; i++)
  123. if(scanf("%s", puzzle[i]) != ) return false;
  124. return true;
  125. }
  126.  
  127. int main() {
  128. int kase = ;
  129. while(read()) {
  130. if(++kase != ) printf("\n");
  131. solver.init();
  132. for(int r = ; r < ; r++)
  133. for(int c = ; c < ; c++)
  134. for(int v = ; v < ; v++)
  135. if(puzzle[r][c] == '-' || puzzle[r][c] == 'A'+v) {
  136. vector<int> columns;
  137. columns.push_back(encode(SLOT, r, c));
  138. columns.push_back(encode(ROW, r, v));
  139. columns.push_back(encode(COL, c, v));
  140. columns.push_back(encode(SUB, (r/)*+c/, v));
  141. solver.addRow(encode(r, c, v), columns);
  142. }
  143.  
  144. vector<int> ans;
  145. assert(solver.solve(ans));
  146.  
  147. for(int i = ; i < ans.size(); i++) {
  148. int r, c, v;
  149. decode(ans[i], r, c, v);
  150. puzzle[r][c] = 'A'+v;
  151. }
  152. for(int i = ; i < ; i++)
  153. printf("%s\n", puzzle[i]);
  154. }
  155. return ;
  156. }

搜索: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. 第9次Scrum会议(10/21)【欢迎来怼】

    一.小组信息 队名:欢迎来怼小组成员队长:田继平成员:李圆圆,葛美义,王伟东,姜珊,邵朔,冉华小组照片 二.开会信息 时间:2017/10/21 17:20~17:45,总计25min.地点:东北师范 ...

  2. Haproxy + Rabbit 集群 简要介绍

    # 两台主机都安装上rabbitMQ yum install -y rabbitmq-server   # 两台主机都配置/etc/hosts文件 192.168.23.10 rabbitmq1 19 ...

  3. (一)MySQL基础篇

    1.mysql简介 数据库(Database)是按照数据结构来组织.存储和管理数据的仓库. 主流的数据库有:sqlserver,mysql,Oracle.SQLite.Access.MS SQL Se ...

  4. Halcon 笔记3 形态学

    Halcon 三大数据类型: (1)图像 (2)区域 (3)XLD  查看时间工具 如果想让图像减少,则进行腐蚀(或者使用开运算),反之,则进行膨胀(或闭运算) 腐蚀后再进行膨胀,相当于进行开运算.因 ...

  5. SQL Server bit数据类型

    bit值保存为1/0,1代表true,0代表false读取数据库数据时,可以直接用bool型读取该字段,会直接转换为true/false 数据库表结构 CREATE TABLE [dbo].[BitT ...

  6. H5跳转到百度地图并定位

    找了半天的JS api,发现没有,后来发现这个叫 url api,让我好找. 官方文档: http://lbsyun.baidu.com/index.php?title=uri/api/web : 简 ...

  7. Importing/Indexing database (MySQL or SQL Server) in Solr using Data Import Handler--转载

    原文地址:https://gist.github.com/maxivak/3e3ee1fca32f3949f052 Install Solr download and install Solr fro ...

  8. BZOJ 1222 产品加工(DP)

    某加工厂有A.B两台机器,来加工的产品可以由其中任何一台机器完成,或者两台机器共同完成.由于受到机器性能和产品特性的限制,不同的机器加工同一产品所需的时间会不同,若同时由两台机器共同进行加工,所完成任 ...

  9. 【bzoj1430】小猴打架 Prufer序列

    题目描述 给出 $n$ 个点,每次选择任意一条边,问这样 $n-1$ 次后得到一棵树的方案数是多少. 输入 一个整数N. 输出 一行,方案数mod 9999991. 样例输入 4 样例输出 96 题解 ...

  10. 【Mybatis】<foreach>标签在mybatis中的使用

    mapper.xml如下: <select id="selectCkspcb" parameterType="java.util.Map" resultT ...