题目链接: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都应该建立行列关系。

 #include<iostream>
#include<cstdio>
#include<vector>
#include<cstring>
#include<string>
#include<algorithm>
#include<set>
#include<cstdlib>
#include<map>
#include<queue>
#include<cmath>
using namespace std;
typedef long long ll;
const int MN = ;
const int MM = ;
const int MNN = MN * MM + ;
struct DLX { int n, m, size;//一共n行m列,size个节点
int U[MNN], D[MNN], L[MNN], R[MNN], row[MNN], col[MNN];//第i个节点的上U下D左L右R,所在位置row行col列
int H[MNN], S[MM];//H数组记录行选择指针,S数组记录覆盖个数
int ansd, ans[MN];//res记录行个数,ans数组记录可行解
void init(int x, int y) {//初始化空表
n = x, m = y;
for (int i = ; i <= m; ++i) {//其中0节点作为head节点,其他作为列首节点
U[i] = D[i] = i;
L[i] = i - ;
R[i] = i + ;
}
R[m] = ; L[] = m;
size = m;
memset(S, , sizeof(S));
memset(H, -, sizeof(H));
}
void Link(int r, int c) {
size++; row[size] = r; col[size] = c; S[c]++;//节点数加一,设置s节点所处位置,以及S列覆盖个数加一
D[size] = D[c]; U[D[c]] = size;//将s节点插入对应列中
U[size] = c; D[c] = size;
if (H[r] < )//如果该行没有元素,H[r]标记该行起始节点
H[r] = L[size] = R[size] = size;
else {//将该节点插入该行第一个节点后面
R[size] = R[H[r]];
L[R[H[r]]] = size;
L[size] = H[r];
R[H[r]] = size;
}
}
//精确覆盖
void remove(int c) {//删除c列
L[R[c]] = L[c]; R[L[c]] = R[c];
//删除该列上的元素对应的行
for (int i = D[c]; i != c; i = D[i]) {//枚举该列元素
for (int j = R[i]; j != i; j = R[j]) {//枚举列的某个元素所在行遍历
U[D[j]] = U[j];
D[U[j]] = D[j];
//将该列上的S数组减一
--S[col[j]];
}
}
}
void resume(int c) {//恢复c列
for (int i = U[c]; i != c; i = U[i]) {//枚举该列元素
for (int j = L[i]; j != i; j = L[j]) {
U[D[j]] = j; D[U[j]] = j;
++S[col[j]];
}
}
L[R[c]] = c; R[L[c]] = c;
}
bool dancing(int deep) {
if (R[] == ) {//当矩阵为空时,说明找到一个可行解,算法终止
ansd = deep;
return true;
}
int c = R[];//找到节点数最少的列,枚举这列上的所有行
for (int i = R[]; i != ; i = R[i]) {
if (S[i] < S[c]) {
c = i;
}
}
remove(c);//删除节点数最少的列
for (int i = D[c]; i != c; i = D[i]) {
ans[deep] = row[i];//将行r放入当前解
for (int j = R[i]; j != i; j = R[j])//行上节点对应的列上进行删除
remove(col[j]);
//进入下一层
if (dancing(deep + ))return true;
//对行上的节点对应的列进行恢复
for (int j = L[i]; j != i; j = L[j])
resume(col[j]);
}
//恢复节点数最少列
resume(c);
return false;
}
};
DLX dzl;
int mp[][];
int x[];
int y[];
int kk[];
int main() {
char s[];
while (cin >> s) {
if (strcmp(s, "end") == )
break;
for (int i = ; i < ; i++) {
int xx = i / ;
int yy = i % ;
if (s[i] == '.')
mp[xx + ][yy + ] = ;
else
mp[xx + ][yy + ] = s[i] - '';
}
dzl.init(, );
int len = ;
for (int i = ; i <= ; i++) {
for (int j = ; j <= ; j++) {
if (mp[i][j] == ) {
for (int k = ; k <= ; k++) {
dzl.Link(len, (i - ) * + j);
dzl.Link(len, (i - ) * + k + );
dzl.Link(len, (j - ) * + k + );
dzl.Link(len, (((i - ) / ) * + ((j + ) / ) - ) * + k + );
x[len] = i, y[len] = j, kk[len] = k;
len++;
}
}
else {
int k = mp[i][j];
dzl.Link(len, (i - ) * + j);
dzl.Link(len, (i - ) * + k + );
dzl.Link(len, (j - ) * + k + );
dzl.Link(len, (((i - ) / ) * + ((j + ) / ) - ) * + k + );
x[len] = i, y[len] = j, kk[len] = k;
len++;
}
}
}
dzl.dancing();
for (int i = ; i < dzl.ansd; i++) {
int r = dzl.ans[i];
mp[x[r]][y[r]] = kk[r];
}
for (int i = ; i <= ; i++) {
for (int j = ; j <= ; j++) {
printf("%d", mp[i][j]);
}
}
puts("");
}
}

[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. vue axios 拦截器

    前言 项目中需要验证登录用户身份是否过期,是否有权限进行操作,所以需要根据后台返回不同的状态码进行判断. 第一次使用拦截器,文章中如有不对的地方还请各位大佬帮忙指正谢谢. 正文 axios的拦截器分为 ...

  2. 记录几个ui框架

    Web前端领域最近几年发展的特别迅速,可以说是百家争鸣.Web前端框架就是为了节约开发成本和时间,一般开发一个项目都会用到前端框架(除非自己有前端开发团队).对于现在的开发者来说,都向着全栈方向发展, ...

  3. org.hibernate.hql.ast.QuerySyntaxException: tb_voteoption is not mapped [from tb_voteoption where voteID=?]

    转自:https://www.cnblogs.com/albert1017/archive/2012/08/25/2656873.html org.hibernate.hql.ast.QuerySyn ...

  4. 初步理解React

    1.组件化 在 MV* 架构出现之前,组件主要分为两种: 狭义上的组件,又称为 UI 组件,比如 Tabs 组件.Dropdown 组件.组件主要围绕在交互 动作上的抽象,针对这些交互动作,利用 Ja ...

  5. Lamabda Where Select Find First等区别

    using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace Cons ...

  6. python的list内存分配算法

    前提:python为了提高效率会为list预先分配一定的内存空间供其使用,避免在每次append等操作都去申请内存,下面简单分析下list的内存分配算法,主要就是两段. 1.当没有元素时,newsiz ...

  7. 2018-11-01-weekly

    Algorithm 107. 二叉树的层次遍历 II What 给定一个二叉树,返回其节点值自底向上的层次遍历. (即按从叶子节点所在层到根节点所在的层,逐层从左向右遍历).例如:给定二叉树 [3,9 ...

  8. 黑客教父郭盛华:提升家庭WiFi的10个方法

    中国黑客教父,知名网络安全专家郭盛华曾发博文表示:“WiFi是互联网发展过程中最重要的发展之一,虚拟世界没有百分百的安全,所以杀毒软件并不可以抵抗全部的黑客攻击.“ 用户WiFi密码尽量不要使用简单单 ...

  9. ORM多表操作上

    一.创建模型 例:我们来假定下面这些概念,字段和关系 作者模型:一个作者有姓名和年龄. 作者详细模型:把作者的详情放到详情表,包含生日,手机号,家庭住址等信息.作者详情模型和作者模型之间是一对一(on ...

  10. 【leetcode】816. Ambiguous Coordinates

    题目如下: 解题思路:我的方案是先把S拆分成整数对,例如S='1230',先拆分成(1,230),(12,30),(123,0),然后再对前面整数对进行加小数点处理.比如(12,30)中的12可以加上 ...