[poj3074]Sudoku(舞蹈链)
题目链接: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(舞蹈链)的更多相关文章
- POJ3074 Sudoku 舞蹈链 DLX
欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目(传送门) 题意概括 给出一个残缺的数独,求解. 题解 DLX + 矩阵构建 (两个传送门) 代码 #include & ...
- POJ3076 Sudoku 舞蹈链 DLX
欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目(传送门) 题意概括 给出一个残缺的16*16数独,求解. 题解 DLX + 矩阵构建 (两个传送门) 学完这个之后,再 ...
- POJ2676 Sudoku 舞蹈链 DLX
欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目(传送门) 题意概括 给出一个残缺的数独,求解.SPJ 题解 DLX + 矩阵构建 (两个传送门) 代码 #includ ...
- 算法实践——舞蹈链(Dancing Links)算法求解数独
在“跳跃的舞者,舞蹈链(Dancing Links)算法——求解精确覆盖问题”一文中介绍了舞蹈链(Dancing Links)算法求解精确覆盖问题. 本文介绍该算法的实际运用,利用舞蹈链(Dancin ...
- 舞蹈链 DLX
欢迎访问——该文出处-博客园-zhouzhendong 去博客园看该文章--传送门 舞蹈链是一个非常玄学的东西…… 问题模型 精确覆盖问题:在一个01矩阵中,是否可以选出一些行的集合,使得在这些行的集 ...
- 转载 - 算法实践——舞蹈链(Dancing Links)算法求解数独
出处:http://www.cnblogs.com/grenet/p/3163550.html 在“跳跃的舞者,舞蹈链(Dancing Links)算法——求解精确覆盖问题”一文中介绍了舞蹈链(Dan ...
- 跳跃的舞者,舞蹈链(Dancing Links)算法——求解精确覆盖问题
精确覆盖问题的定义:给定一个由0-1组成的矩阵,是否能找到一个行的集合,使得集合中每一列都恰好包含一个1 例如:如下的矩阵 就包含了这样一个集合(第1.4.5行) 如何利用给定的矩阵求出相应的行的集合 ...
- DLX舞蹈链 hdu5046
题意: 在N个城市选出K个城市,建飞机场(1 ≤ N ≤ 60,1 ≤ K ≤ N),N个城市给出坐标,选择这K个机场,使得从城市到距离自己最近的机场的 最大的距离 最小. 输出这个最小值. 思路: ...
- [转] 舞蹈链(Dancing Links)——求解精确覆盖问题
转载自:http://www.cnblogs.com/grenet/p/3145800.html 精确覆盖问题的定义:给定一个由0-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- ...
- Node.JS-经典教程
目录 1. 下载地址 2. 目录 1. 下载地址 https://www.cnblogs.com/coco56/p/11223189.html 在视频教程那里 2. 目录 00课件.rar 01.历史 ...
- python基础--3 列表
#list类#li是list类的一个对象li=[11,22,33,22,44] #参数#在原来值最后进行整个作为元素追加 # li.append((11,22,33))#对列表本身进行操作,appen ...
- ps:界面概览
首先我们来认识一下Photoshop的界面组成,如下图是一个典型的界面.为了方便识别,我们加上了颜色和数字. 1:顶部的红色区域是菜单栏,包括色彩调整之类的命令都存放在从菜单栏中.在我们的教程中使用[ ...
- uboot tag存储主要部分代码
https://www.cnblogs.com/pokerface/p/5217106.html cmd_bootm.c //传递给内核的参数 int do_bootm (cmd_t ...
- drf 搜索功能
from django_filters.rest_framework import DjangoFilterBackend from rest_framework import viewsets fr ...
- linux运维、架构之路-数据库迁移
一.wordpress搭建 1.wordpress下载部署 cd /server/tools/ wget https://cn.wordpress.org/wordpress-4.8.1-zh_CN. ...
- [luogu]P1041 传染病控制[dfs]
[luogu]P1041 传染病控制 ——!x^n+y^n=z^n 题目背景 近来,一种新的传染病肆虐全球.蓬莱国也发现了零星感染者,为防止该病在蓬莱国大范围流行,该国政府决定不惜一切代价控制传染病的 ...
- 【Java】JSONObject学习
介绍 JSONObject只是一种数据结构,可以理解为JSON格式的数据结构(key-value 结构),可以使用put方法给json对象添加元素.JSONObject可以很方便的转换成字符串,也可以 ...
- vue实现动态显示与隐藏底部导航的方法分析
本文实例讲述了vue实现动态显示与隐藏底部导航的方法.分享给大家供大家参考,具体如下: 在日常项目中,总有几个页面是要用到底部导航的,总有那么些个页面,是不需要底部导航的,这里列举一下页面底部导航的显 ...