题目链接:http://poj.org/problem?id=3074

舞蹈链精确覆盖的经典题目,一个数独每个位置的要求,可以得到以下四个约束
1.每个位置有且只有一个数字
2.每个位置的数字在一行只能出现一次
3.每个位置的数字在一列只能出现一次
4.每个位置的数字在一个宫格内只能出现一次
然后针对每个位置可以建立舞蹈链了
前81列,为1条件的约束
82-162列,为2条件的约束
163-243列,为3条件的约束
244-324列,为4条件的约束
则舞蹈链行数为确定的点数+未确定的点数*9,列数为324。
如果i行j列为数k,对应行则在(i - 1) 9 + j列,(i - 1) 9 + k + 81列, (j - 1) 9 + k + 162列,(((i - 1) / 3) 3 + ((j + 2) / 3) - 1)* 9 + k + 243列建立。
如果i行j列为未知数,则k为1-9,对于每个k都应该建立行列关系。

  1. #include<iostream>
  2. #include<cstdio>
  3. #include<vector>
  4. #include<cstring>
  5. #include<string>
  6. #include<algorithm>
  7. #include<set>
  8. #include<cstdlib>
  9. #include<map>
  10. #include<queue>
  11. #include<cmath>
  12. using namespace std;
  13. typedef long long ll;
  14. const int MN = ;
  15. const int MM = ;
  16. const int MNN = MN * MM + ;
  17. struct DLX {
  18.  
  19. int n, m, size;//一共n行m列,size个节点
  20. int U[MNN], D[MNN], L[MNN], R[MNN], row[MNN], col[MNN];//第i个节点的上U下D左L右R,所在位置row行col列
  21. int H[MNN], S[MM];//H数组记录行选择指针,S数组记录覆盖个数
  22. int ansd, ans[MN];//res记录行个数,ans数组记录可行解
  23. void init(int x, int y) {//初始化空表
  24. n = x, m = y;
  25. for (int i = ; i <= m; ++i) {//其中0节点作为head节点,其他作为列首节点
  26. U[i] = D[i] = i;
  27. L[i] = i - ;
  28. R[i] = i + ;
  29. }
  30. R[m] = ; L[] = m;
  31. size = m;
  32. memset(S, , sizeof(S));
  33. memset(H, -, sizeof(H));
  34. }
  35. void Link(int r, int c) {
  36. size++; row[size] = r; col[size] = c; S[c]++;//节点数加一,设置s节点所处位置,以及S列覆盖个数加一
  37. D[size] = D[c]; U[D[c]] = size;//将s节点插入对应列中
  38. U[size] = c; D[c] = size;
  39. if (H[r] < )//如果该行没有元素,H[r]标记该行起始节点
  40. H[r] = L[size] = R[size] = size;
  41. else {//将该节点插入该行第一个节点后面
  42. R[size] = R[H[r]];
  43. L[R[H[r]]] = size;
  44. L[size] = H[r];
  45. R[H[r]] = size;
  46. }
  47. }
  48. //精确覆盖
  49. void remove(int c) {//删除c列
  50. L[R[c]] = L[c]; R[L[c]] = R[c];
  51. //删除该列上的元素对应的行
  52. for (int i = D[c]; i != c; i = D[i]) {//枚举该列元素
  53. for (int j = R[i]; j != i; j = R[j]) {//枚举列的某个元素所在行遍历
  54. U[D[j]] = U[j];
  55. D[U[j]] = D[j];
  56. //将该列上的S数组减一
  57. --S[col[j]];
  58. }
  59. }
  60. }
  61. void resume(int c) {//恢复c列
  62. for (int i = U[c]; i != c; i = U[i]) {//枚举该列元素
  63. for (int j = L[i]; j != i; j = L[j]) {
  64. U[D[j]] = j; D[U[j]] = j;
  65. ++S[col[j]];
  66. }
  67. }
  68. L[R[c]] = c; R[L[c]] = c;
  69. }
  70. bool dancing(int deep) {
  71. if (R[] == ) {//当矩阵为空时,说明找到一个可行解,算法终止
  72. ansd = deep;
  73. return true;
  74. }
  75. int c = R[];//找到节点数最少的列,枚举这列上的所有行
  76. for (int i = R[]; i != ; i = R[i]) {
  77. if (S[i] < S[c]) {
  78. c = i;
  79. }
  80. }
  81. remove(c);//删除节点数最少的列
  82. for (int i = D[c]; i != c; i = D[i]) {
  83. ans[deep] = row[i];//将行r放入当前解
  84. for (int j = R[i]; j != i; j = R[j])//行上节点对应的列上进行删除
  85. remove(col[j]);
  86. //进入下一层
  87. if (dancing(deep + ))return true;
  88. //对行上的节点对应的列进行恢复
  89. for (int j = L[i]; j != i; j = L[j])
  90. resume(col[j]);
  91. }
  92. //恢复节点数最少列
  93. resume(c);
  94. return false;
  95. }
  96. };
  97. DLX dzl;
  98. int mp[][];
  99. int x[];
  100. int y[];
  101. int kk[];
  102. int main() {
  103. char s[];
  104. while (cin >> s) {
  105. if (strcmp(s, "end") == )
  106. break;
  107. for (int i = ; i < ; i++) {
  108. int xx = i / ;
  109. int yy = i % ;
  110. if (s[i] == '.')
  111. mp[xx + ][yy + ] = ;
  112. else
  113. mp[xx + ][yy + ] = s[i] - '';
  114. }
  115. dzl.init(, );
  116. int len = ;
  117. for (int i = ; i <= ; i++) {
  118. for (int j = ; j <= ; j++) {
  119. if (mp[i][j] == ) {
  120. for (int k = ; k <= ; k++) {
  121. dzl.Link(len, (i - ) * + j);
  122. dzl.Link(len, (i - ) * + k + );
  123. dzl.Link(len, (j - ) * + k + );
  124. dzl.Link(len, (((i - ) / ) * + ((j + ) / ) - ) * + k + );
  125. x[len] = i, y[len] = j, kk[len] = k;
  126. len++;
  127. }
  128. }
  129. else {
  130. int k = mp[i][j];
  131. dzl.Link(len, (i - ) * + j);
  132. dzl.Link(len, (i - ) * + k + );
  133. dzl.Link(len, (j - ) * + k + );
  134. dzl.Link(len, (((i - ) / ) * + ((j + ) / ) - ) * + k + );
  135. x[len] = i, y[len] = j, kk[len] = k;
  136. len++;
  137. }
  138. }
  139. }
  140. dzl.dancing();
  141. for (int i = ; i < dzl.ansd; i++) {
  142. int r = dzl.ans[i];
  143. mp[x[r]][y[r]] = kk[r];
  144. }
  145. for (int i = ; i <= ; i++) {
  146. for (int j = ; j <= ; j++) {
  147. printf("%d", mp[i][j]);
  148. }
  149. }
  150. puts("");
  151. }
  152. }

[poj3074]Sudoku(舞蹈链)的更多相关文章

  1. POJ3074 Sudoku 舞蹈链 DLX

    欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目(传送门) 题意概括 给出一个残缺的数独,求解. 题解 DLX + 矩阵构建  (两个传送门) 代码 #include & ...

  2. POJ3076 Sudoku 舞蹈链 DLX

    欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目(传送门) 题意概括 给出一个残缺的16*16数独,求解. 题解 DLX + 矩阵构建  (两个传送门) 学完这个之后,再 ...

  3. POJ2676 Sudoku 舞蹈链 DLX

    欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目(传送门) 题意概括 给出一个残缺的数独,求解.SPJ 题解 DLX + 矩阵构建  (两个传送门) 代码 #includ ...

  4. 算法实践——舞蹈链(Dancing Links)算法求解数独

    在“跳跃的舞者,舞蹈链(Dancing Links)算法——求解精确覆盖问题”一文中介绍了舞蹈链(Dancing Links)算法求解精确覆盖问题. 本文介绍该算法的实际运用,利用舞蹈链(Dancin ...

  5. 舞蹈链 DLX

    欢迎访问——该文出处-博客园-zhouzhendong 去博客园看该文章--传送门 舞蹈链是一个非常玄学的东西…… 问题模型 精确覆盖问题:在一个01矩阵中,是否可以选出一些行的集合,使得在这些行的集 ...

  6. 转载 - 算法实践——舞蹈链(Dancing Links)算法求解数独

    出处:http://www.cnblogs.com/grenet/p/3163550.html 在“跳跃的舞者,舞蹈链(Dancing Links)算法——求解精确覆盖问题”一文中介绍了舞蹈链(Dan ...

  7. 跳跃的舞者,舞蹈链(Dancing Links)算法——求解精确覆盖问题

    精确覆盖问题的定义:给定一个由0-1组成的矩阵,是否能找到一个行的集合,使得集合中每一列都恰好包含一个1 例如:如下的矩阵 就包含了这样一个集合(第1.4.5行) 如何利用给定的矩阵求出相应的行的集合 ...

  8. DLX舞蹈链 hdu5046

    题意: 在N个城市选出K个城市,建飞机场(1 ≤ N ≤ 60,1 ≤ K ≤ N),N个城市给出坐标,选择这K个机场,使得从城市到距离自己最近的机场的 最大的距离 最小. 输出这个最小值. 思路: ...

  9. [转] 舞蹈链(Dancing Links)——求解精确覆盖问题

    转载自:http://www.cnblogs.com/grenet/p/3145800.html 精确覆盖问题的定义:给定一个由0-1组成的矩阵,是否能找到一个行的集合,使得集合中每一列都恰好包含一个 ...

随机推荐

  1. 2018-10-2-win10-uwp-win2d-特效

    title author date CreateTime categories win10 uwp win2d 特效 lindexi 2018-10-02 21:20:46 +0800 2018-6- ...

  2. Node.JS-经典教程

    目录 1. 下载地址 2. 目录 1. 下载地址 https://www.cnblogs.com/coco56/p/11223189.html 在视频教程那里 2. 目录 00课件.rar 01.历史 ...

  3. python基础--3 列表

    #list类#li是list类的一个对象li=[11,22,33,22,44] #参数#在原来值最后进行整个作为元素追加 # li.append((11,22,33))#对列表本身进行操作,appen ...

  4. ps:界面概览

    首先我们来认识一下Photoshop的界面组成,如下图是一个典型的界面.为了方便识别,我们加上了颜色和数字. 1:顶部的红色区域是菜单栏,包括色彩调整之类的命令都存放在从菜单栏中.在我们的教程中使用[ ...

  5. uboot tag存储主要部分代码

    https://www.cnblogs.com/pokerface/p/5217106.html     cmd_bootm.c //传递给内核的参数      int do_bootm (cmd_t ...

  6. drf 搜索功能

    from django_filters.rest_framework import DjangoFilterBackend from rest_framework import viewsets fr ...

  7. linux运维、架构之路-数据库迁移

    一.wordpress搭建 1.wordpress下载部署 cd /server/tools/ wget https://cn.wordpress.org/wordpress-4.8.1-zh_CN. ...

  8. [luogu]P1041 传染病控制[dfs]

    [luogu]P1041 传染病控制 ——!x^n+y^n=z^n 题目背景 近来,一种新的传染病肆虐全球.蓬莱国也发现了零星感染者,为防止该病在蓬莱国大范围流行,该国政府决定不惜一切代价控制传染病的 ...

  9. 【Java】JSONObject学习

    介绍 JSONObject只是一种数据结构,可以理解为JSON格式的数据结构(key-value 结构),可以使用put方法给json对象添加元素.JSONObject可以很方便的转换成字符串,也可以 ...

  10. vue实现动态显示与隐藏底部导航的方法分析

    本文实例讲述了vue实现动态显示与隐藏底部导航的方法.分享给大家供大家参考,具体如下: 在日常项目中,总有几个页面是要用到底部导航的,总有那么些个页面,是不需要底部导航的,这里列举一下页面底部导航的显 ...