利用 Dancing Link 来解数独

详细的能够看    lrj 的训练指南 和 《 Dancing Links 在搜索中的应用 》这篇论文

Dancing Link 来求解数独 , 是通过求解精确覆盖

精确覆盖就是给出一个 01 矩阵 , 要求我们选择一些行 , 使得每一列有且仅有一个 1

对于数独问题 , 行就是我们的选择 , 即在第 i 行 第 j 列 放上 数字 k , 所以我们最多有 i * j * k 中选择

假设某些位置( x , y  )已经放了数字 a , 那么我们的选择仅仅能是 ( x , y , a ) , 否则的话, 我们能够选择 ( x , y , 1 ~ 9 )

对于列 , 也就是我们须要满足的条件 , 这里有 4 大类条件:

1. 第 x 行 第 y 列要有 数字

2. 第 x 行 要有 数字 y

3. 第 x 列 要有 数字 y

4. 第 x 个宫要有数字 y

所以总共同拥有 9*9*4 列 ( 如果 9*9*4 的数独的话 )

然后我们仅仅要进行DLX即可了

#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <vector>
using namespace std; const int maxn = 9 * 9 * 4 + 10 ;
const int maxr = 9 * 9 * 9 + 10 ;
const int maxnode = maxr * 4 + maxr + 10 ; #define FOR( i , A , s ) for( int i = A[s] ; i != s ; i = A[i] ) struct DLX{
// maxn 列数 , maxnode 总节点数 , maxr 行数
int n , sz ;
int S[maxn] ; int row[maxnode] , col[maxnode] ;
int L[maxnode] , R[maxnode] , U[maxnode] , D[maxnode] ;
int H[maxr] ; int ansd , ans[maxr] ; void init( int N ) {
n = N ;
// 第一行的虚拟结点
for( int i = 0 ; i <= n ; i ++ ) {
U[i] = D[i] = i ;
L[i] = i - 1 ;
R[i] = i + 1 ;
}
R[n] = 0 ; L[0] = n ;
sz = n + 1 ;
// 每一列的个数
memset( S , 0 , sizeof(S) ) ;
// H[i] = -1 表示这一行还没有 1
// 否则表示第一个 1 的 sz 是多少
memset( H , -1 , sizeof(H)) ;
} // 在第r行第c列加入一个1
void Link( int r , int c ) {
row[sz] = r ;
col[sz] = c ;
S[c] ++ ; D[sz] = c ; U[sz] = U[c] ;
D[U[c]] = sz ; U[c] = sz ; if( H[r] < 0 ) { H[r] = L[sz] = R[sz] = sz ; }
else{
R[sz] = H[r] ;
L[sz] = L[H[r]] ;
R[L[sz]] = sz ;
L[R[sz]] = sz ;
} sz ++ ; } // 删除 第 c 列
void remove ( int c ) {
// 删除虚拟结点中的 c 列
L[R[c]] = L[c] ;
R[L[c]] = R[c] ;
// 从 c 列向下遍历
FOR( i , D , c ) {
// 删除遍历到的行
FOR( j , R , i ) {
D[U[j]] = D[j] ;
U[D[j]] = U[j] ;
-- S[col[j]] ;
}
}
} // 恢复第 c 列
void restore( int c ) {
FOR( i , U , c ) {
FOR( j , L , i ) {
++S[col[j]] ;
U[D[j]] = D[U[j]] = j ;
}
}
L[R[c]] = R[L[c]] = c ;
} bool dfs( int d ) {
// 假设已经没有列了 , 算法结束
if( R[0] == 0 ) {
ansd = d ;
return true ;
} // 找到 s 最小的列 , 加快搜索的速度
int c = R[0] ;
FOR( i , R , 0 ) {
if( S[i] < S[c] ) c = i ;
} // 删除第 c 列
remove( c ) ; // 遍历选中列中有1的行
FOR( i , D , c ) {
ans[d] = row[i] ;
// 删除选中行中有1的列
FOR( j , R , i ) {
remove( col[j] ) ;
}
if( dfs( d + 1 ) ) return true ;
// 回复删除掉的列
FOR( j , L , i ) {
restore( col[j] ) ;
}
}
restore( c ) ;
return false ;
} bool solve() {
if( !dfs(0) ) return false ;
return true ;
}
} dlx ; int ans[15][15] ; const int SLOT = 0 ;
const int ROW = 1 ;
const int COL = 2 ;
const int SUB = 3 ; inline int encode ( int a , int b , int c ) {
return a * 9 * 9 + b * 9 + c + 1 ;
} int main(){
char str[5] ;
int casn = 0 ;
while( scanf( "%s" , str ) != EOF ) { if( str[0] == '?' ) {
ans[0][0] = 0 ;
}else{
ans[0][0] = str[0] - '0' ;
}
for( int i = 0 ; i < 9 ; i ++ ) {
for( int j = 0 ; j < 9 ; j ++ ) {
if( i == 0 && j == 0 ) continue ;
scanf( "%s" , str ) ;
if( str[0] == '?' )
ans[i][j] = 0 ;
else
ans[i][j] = str[0] - '0' ;
}
} if( casn ++ ) {
puts( "" ) ;
} dlx.init( 9 * 9 * 4 ) ; for( int i = 0 ; i < 9 ; i ++ ) {
for( int j = 0 ; j < 9 ; j ++ ) {
for( int k = 0 ; k < 9 ; k ++ ) {
int rr = encode( i , j , k ) ;
if( ans[i][j] == 0 || ans[i][j] == k + 1 ) {
dlx.Link( rr , encode( SLOT , i , j ) ) ;
dlx.Link( rr , encode( ROW , i , k ) ) ;
dlx.Link( rr , encode( COL , j , k ) ) ;
dlx.Link( rr , encode( SUB , ( i / 3 ) * 3 + j / 3 , k ) ) ; }
}
}
} dlx.solve() ;
for( int i = 0 ; i < dlx.ansd ; i ++ ) {
int r , c , v ;
int t = dlx.ans[i] ;
t -- ;
v = t % 9 ;
t /= 9 ;
c = t % 9 ;
t /= 9 ;
r = t ;
ans[r][c] = v + 1 ;
}
for( int i = 0 ; i < 9 ; i ++ ) {
for( int j = 0 ; j < 9 ; j ++ ) {
printf( j == 8 ?"%d\n" : "%d " , ans[i][j] ) ;
}
}
}
return 0 ;
}

hdu 1426 Sudoku Killer ( Dancing Link 精确覆盖 )的更多相关文章

  1. HDU 1426 Sudoku Killer(dfs 解数独)

    传送门: http://acm.hdu.edu.cn/showproblem.php?pid=1426 Sudoku Killer Time Limit: 2000/1000 MS (Java/Oth ...

  2. hdu 1426:Sudoku Killer(DFS深搜,进阶题目,求数独的解)

    Sudoku Killer Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Tot ...

  3. hdu 1426 Sudoku Killer (dfs)

    Sudoku Killer Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Tot ...

  4. dancing link 精确覆盖 重复覆盖 (DLX)

    申明:因为转载的没有给出转载链接,我就把他的链接附上,请尊重原创: http://www.cnblogs.com/-sunshine/p/3358922.html 如果谁知道原创链接 给一下,请尊重原 ...

  5. hdu 1426 Sudoku Killer

    题目:http://acm.hdu.edu.cn/showproblem.php?pid=1426 #include<stdio.h> #include<math.h> #in ...

  6. HDU 1426 Sudoku Killer(搜索)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1426 题意很明确,让你解一个9*9的数独. DFS即可. #include <cstdio> ...

  7. HDU 1426 Sudoku Killer【DFS 数独】

    自从2006年3月10日至11日的首届数独世界锦标赛以后,数独这项游戏越来越受到人们的喜爱和重视. 据说,在2008北京奥运会上,会将数独列为一个单独的项目进行比赛,冠军将有可能获得的一份巨大的奖品— ...

  8. HDU 1426 Sudoku Killer (回溯 + 剪枝)

    本文链接:http://i.cnblogs.com/EditPosts.aspx?postid=5398818 题意: 给你一个 9*9 的矩阵,同一行相邻的两个元素用一个空格分开.其中1-9代表该位 ...

  9. HDU 3111 Sudoku ( Dancing Links 精确覆盖模型 )

    推荐两篇学DLX的博文: http://bbs.9ria.com/thread-130295-1-1.html(这篇对DLX的工作过程演示的很详细) http://yzmduncan.iteye.co ...

随机推荐

  1. Linux shell用法和技巧(转)

    使用Linux shell是我每天的基本工作,但我经常会忘记一些有用的shell命令和l技巧.当然,命令我能记住,但我不敢说能记得如何用它执行某个特定任务.于是,我开始在一个文本文件里记录这些用法,并 ...

  2. 使用GDAL图书馆RPC校正问题

    很快就会GDAL库更新1.11版本号之后,在发现之前写RPC像方误差修正模型校准结果特别大(在更新结果之前的版本号和PCI结果一致).所以初步推断是GDAL库的bug,经过各个參数改动发现原来是指定的 ...

  3. 使用crontab创建 linux 系统定时任务#

    任务1: 每隔1分钟,运行一次 /home/sn/yeelink.sh文件 ,用于上传数据到www.yeelink.net 1. 先在当时目录里面创建一个cronfile文件 vim cronfile ...

  4. not accessible due to restriction on required library

    The type AWTUtilities is not accessible due to restriction on required library D:\Program Files\jdk1 ...

  5. 系统负载测试工具-LoadRunner

    LoadRunner的主要作用是对系统压力测试进行分析 与之相类似的工具是:badboy:录制脚本工具+jmeter:分析结果工具

  6. 【Web探索之旅】第二部分第五课:响应式网站和移动应用

    内容简介 1.第二部分第五课:响应式网站和移动应用 2.第三部分第一课预告:服务器 第二部分第五课:响应式网站和移动应用 在我们开始聊响应式网站之前,我们可以聊聊移动App(App是Applicati ...

  7. 搭建SSH

    搭建SSH详细步骤及相关说明   因为手里已有相关jar,为方便我搭建的是:Struts2.0+Hibernate3.3+Spring3.0,数据库:MySQL 如果想搭建最新的,在官网上下载最新ja ...

  8. HDU 3715 Go Deeper(2-sat)

    HDU 3715 Go Deeper 题目链接 题意:依据题意那个函数,构造x数组.问最大能递归层数 思路:转化为2-sat问题,因为x仅仅能是0.1,c仅仅能是0,1.2那么问题就好办了,对于0, ...

  9. [Unity3d]定义自己的鼠标

    [Unity3d]自己定义鼠标 我们在用unity3d开发自己的游戏的时候.自己定义游戏中的鼠标也是常常要用到的.那我就得学学.事实上原理非常easy,先将鼠标给隐藏,然后在鼠标的位置上画出一个自己定 ...

  10. 第十七章——配置SQLServer(3)——配置“对即时负载的优化”

    原文:第十七章--配置SQLServer(3)--配置"对即时负载的优化" 前言: 在第一次执行查询或者存储过程时,会创建执行计划并存储在SQLServer的过程缓存内存中.在很多 ...