推荐两篇学DLX的博文:

http://bbs.9ria.com/thread-130295-1-1.html(这篇对DLX的工作过程演示的很详细)

http://yzmduncan.iteye.com/blog/1151695(这篇对精确覆盖与重复覆盖解释的简洁清晰,模板来自这篇博文)

以下转载:

DLX解决9*9的数独问题,转化为729*324的精确覆盖问题

行:一共9 * 9 * 9 == 729行。一共9 * 9小格,每一格有9种可能性(1 - 9),每一种可能都对应着一行。

列: 一共(9 + 9 + 9) * 9 + 81 == 324 种前面三个9分别代表着9行9列和9小块,乘以9的意思是9种可能(1 - 9),因为每种可能只可以选择一个。 81代表着81个小格,限制着每一个小格只放一个数字。

读入数据后,如果为'.',则建9行,即有1-9种可能,否则建一行,表示某小格只能放确定的某个数字。

以下个人理解:

列: 一共(9 + 9 + 9) * 9 + 81 == 324 种

对于这个(9+9+9)*9 我是这么理解的:一个数a,它在某一行有9个位置可以放,在某一列有9个位置可以放,在某一个3×3小格中有9个位置可以放,所以一共可以放的位置是(9+9+9)个,然后一共9个数字,所以是(9+9+9)*9 。

不知道这样理解是否正确,望大家指教!

#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm> using namespace std; const int INF = << ;
const int SZ = ;
const int MAXR = SZ * SZ * SZ;
const int MAXC = ( SZ+SZ+SZ )*SZ + SZ*SZ; char mat[SZ+][SZ+];
char str[SZ+];
bool maxtri[MAXR+][MAXC+]; //01矩阵
int C[(MAXR+)*(MAXC+)], cnt[MAXC+];
int U[(MAXR+)*(MAXC+)], D[(MAXR+)*(MAXC+)];
int L[(MAXR+)*(MAXC+)], R[(MAXR+)*(MAXC+)];
int head;
int ans[MAXR+];
int val[SZ+][SZ+]; void Remove( int c )
{
int i, j;
L[ R[c] ] = L[c];
R[ L[c] ] = R[c];
for ( i = D[c]; i != c; i = D[i] )
{
for ( j = R[i]; j != i; j = R[j] )
{
U[ D[j] ] = U[j];
D[ U[j] ] = D[j];
--cnt[ C[j] ];
}
}
return;
} void Resume( int c )
{
int i, j;
R[ L[c] ] = c;
L[ R[c] ] = c;
for ( i = D[c]; i != c; i = D[i] )
{
for ( j = R[i]; j != i; j = R[j] )
{
U[ D[j] ] = j;
D[ U[j] ] = j;
++cnt[ C[j] ];
}
}
return;
} bool DFS( int cur )
{
int i, j, c, minv;
if ( R[head] == head )
return true; minv = INF;
for ( i = R[head]; i != head; i = R[i] )
{
if ( cnt[i] < minv )
{
minv = cnt[i];
c = i;
}
} Remove(c);
for ( i = D[c]; i != c; i = D[i] )
{
ans[cur] = (i - )/MAXC;
for( j = R[i]; j != i; j = R[j] )
Remove( C[j] ); if ( DFS( cur + ) ) return true; for( j = R[i]; j != i; j = R[j] )
Resume( C[j] );
} Resume(c);
return false;
} bool build()
{
int i, j, cur, pre, first;
head = ;
for ( i = ; i < MAXC; ++i )
{
R[i] = i + ;
L[i + ] = i;
}
R[ MAXC ] = ;
L[] = MAXC; //列双向链表
for ( j = ; j <= MAXC; ++j )
{
pre = j;
cnt[j] = ;
for ( i = ; i <= MAXR; ++i )
{
if ( maxtri[i][j] )
{
++cnt[j];
cur = i * MAXC + j; //当前节点的编号
C[cur] = j; //当前节点所在列
D[pre] = cur;
U[cur] = pre;
pre = cur;
}
}
U[j] = pre;
D[pre] = j;
if ( !cnt[j] ) return false; //一定无解
} //行双向链表
for ( i = ; i <= MAXR; ++i )
{
pre = first = -;
for ( j = ; j <= MAXC; ++j )
{
if( maxtri[i][j] )
{
cur = i * MAXC + j;
if ( pre == - ) first = cur;
else
{
R[pre] = cur;
L[cur] = pre;
}
pre = cur;
}
}
if ( first != - )
{
R[pre] = first;
L[first] = pre;
}
}
return true;
} /**************以上DLX模板*****************/ void show()
{
for ( int i = ; i <= MAXR; ++i )
{
for ( int j = ; j <= MAXC; ++j )
printf( "%d", maxtri[i][j] );
puts("");
}
return;
} //得到该情况下的01矩阵
void init()
{
memset( maxtri, false, sizeof(maxtri) ); for ( int i = ; i <= SZ; ++i )
{
for ( int j = ; j <= SZ; ++j )
{
int col = ( i - ) * SZ + j; //格子编号(1-81)
if ( mat[i][j] == '?' )
{
for ( int k = ; k <= SZ; ++k )
{
maxtri[ (col - )*SZ + k ][col] = true; //81保证不重复
maxtri[ (col - )*SZ + k ][ + (i - )*SZ + k ] = true; //9行中哪一行
maxtri[ (col - )*SZ + k ][ + (j - )*SZ + k ] = true; //9列中哪一列
maxtri[ (col - )*SZ + k ][ + ((i-)/* + (j-)/ )*SZ + k ] = true;//9小格中哪一个小格
}
}
else
{
int k = mat[i][j] - '';
maxtri[ (col - )*SZ + k ][col] = true;
maxtri[ (col - )*SZ + k ][ + (i - )*SZ + k ] = true;
maxtri[ (col - )*SZ + k ][ + (j - )*SZ + k ] = true;
maxtri[ (col - )*SZ + k ][ + ((i-)/* + (j-)/ )*SZ + k ] = true;
}
}
}
//show(); return;
} void PrintAns()
{
for ( int i = ; i < ; ++i )
{
int num = ans[i];
int gird = num / SZ;
if ( num % SZ ) ++gird;
int aaa = num % SZ;
if ( aaa == ) aaa = ;
int x = (gird-)/SZ+;
int y = (gird-)%SZ+;
val[x][y] = aaa;
} for ( int i = ; i <= SZ; ++i )
{
for ( int j = ; j <= SZ; ++j )
printf( "%d", val[i][j] );
puts("");
}
return;
} int main()
{
//freopen( "in.txt", "r", stdin );
//freopen( "out.txt", "w", stdout );
int T;
scanf( "%d", &T );
while ( T-- )
{
for ( int i = ; i <= SZ; ++i )
scanf( "%s", &mat[i][] );
if ( T ) scanf( "%s", str );
init();
if ( build() )
{
if ( DFS() )
PrintAns();
else puts("impossible");
}
else puts("impossible");
if ( T ) puts("---");
}
return ;
}

昨天比赛做到一个题,正解DLX,不过让薛薛位运算+剪枝直接暴过去了……跪。

为了保险起见,今天学了一下DLX。目前只明白了精确覆盖,对重复覆盖还不是很了解。

那个题似乎不是个很简单的DLX,需要精确覆盖+重复覆盖。orz,再接再厉吧。

不得不说,DLX的剪枝效果真是让人惊叹……

HDU 3111 Sudoku ( Dancing Links 精确覆盖模型 )的更多相关文章

  1. POJ3074 Sudoku —— Dancing Links 精确覆盖

    题目链接:http://poj.org/problem?id=3074 Sudoku Time Limit: 1000MS   Memory Limit: 65536K Total Submissio ...

  2. HDU 2295 Radar (二分 + Dancing Links 重复覆盖模型 )

    以下转自 这里 : 最小支配集问题:二分枚举最小距离,判断可行性.可行性即重复覆盖模型,DLX解之. A*的启发函数: 对当前矩阵来说,选择一个未被控制的列,很明显该列最少需要1个行来控制,所以ans ...

  3. 【转】Dancing Links精确覆盖问题

    原文链接:http://sqybi.com/works/dlxcn/ (只转载过来一部分,全文请看原文,感觉讲得很好~)正文    精确覆盖问题    解决精确覆盖问题    舞蹈步骤    效率分析 ...

  4. HDU 2295 Radar dancing links 重复覆盖

    就是dancing links 求最小支配集,重复覆盖 精确覆盖时:每次缓存数据的时候,既删除行又删除列(这里的删除列,只是删除表头) 重复覆盖的时候:只删除列,因为可以重复覆盖 然后重复覆盖有一个估 ...

  5. hihoCoder #1321 : 搜索五•数独 (Dancing Links ,精确覆盖)

    hiho一下第102周的题目. 原题地址:http://hihocoder.com/problemset/problem/1321 题意:输入一个9*9数独矩阵,0表示没填的空位,输出这个数独的答案. ...

  6. hust 1017 dancing links 精确覆盖模板题

    最基础的dancing links的精确覆盖题目 #include <iostream> #include <cstring> #include <cstdio> ...

  7. ZOJ 3209 Treasure Map (Dancing Links 精确覆盖 )

    题意 :  给你一个大小为 n * m 的矩形 , 坐标是( 0 , 0 ) ~ ( n , m )  .然后给你 p 个小矩形 . 坐标是( x1 , y1 ) ~ ( x2 , y2 ) , 你选 ...

  8. HDU 3335 Divisibility dancing links 重复覆盖

    分析: dlx重复覆盖的巧用,重复覆盖的原理恰好符合本题的筛选方式,即选择一个数后,该数的倍数或约数可以保证在之后的搜索中不会被选择 于是修改一下启发函数,求解最大的重复覆盖即可.   其实不一定不被 ...

  9. HDU 5046 Airport ( Dancing Links 反复覆盖 )

    今年上海网络赛的一道题目 , 跟 HDU 2295 如出一辙 . 就是距离的计算一个是欧几里得距离 , 一个是曼哈顿距离 学完DLX感觉这题好水 ,就是一个裸的反复覆盖 注意下别溢出即可了 #incl ...

随机推荐

  1. cityscape分割3类别数据处理

    cpp: #include "cv.h" #include "highgui.h" #include <iostream> #include < ...

  2. GPGPU::数学基础教程

    并行方向需要学习的数学知识 http://dev.gameres.com/Program/Visual/3D/GPGPU_math_Tutorial.html

  3. matlab vs联调

    vs 和matlab联调,最近真的把我搞挂了要. 首先,怎么进入联调呢.在vs里先设置一下. vs:tools->attach to process,选择matlab,注意此时matlab一定是 ...

  4. ios数据持久化--CoreData框架的介绍和使用

    1.Core Data 是数据持久化存储的最佳方式 2.数据最终的存储类型可以是:SQLite数据库,XML,二进制,内存里,或自定义数据类型 在Mac OS X 10.5Leopard及以后的版本中 ...

  5. 线段树的应用xx中学模拟lites

    跟昨天那个自己写的,没有按照模板来的一看风格就不相类似,今天模拟赛的时候就是用的我的那个自己YY的代码,才拿了10分.个人认为关键的问题应该在于对于数据的处理太过繁琐了,所以回来之后,就拿了大佬的程序 ...

  6. python导包语句执行

    今天在做项目中遇到一个问题,在first_page中引用login的登录方法,第一次执行登录可以正常登录,登录成功后,再选择返回主菜单,回到上个页面,再选择登录时报错“login_class isno ...

  7. Ansible学习 Patterns

    Ansible中ad-hoc命令格式如下:ansible <pattern_goes_here> -m <module_name> -a <arguments>,P ...

  8. 【shell脚本学习-1】

    Shell学习笔记 简介: Shell 是一个用C语言编写的程序,它是用户使用Linux的桥梁.Shell既是一种命令语言,又是一种程序设计语言. Shell 是指一种应用程序,这个应用程序提供了一个 ...

  9. java实现 zip解压缩

    程序实现了ZIP压缩.共分为2部分 : 压缩(compression)与解压(decompression) 大致功能包括用了多态,递归等JAVA核心技术,可以对单个文件和任意级联文件夹进行压缩和解压. ...

  10. Java源码解析——Java IO包

    一.基础知识: 1. Java IO一般包含两个部分:1)java.io包中阻塞型IO:2)java.nio包中的非阻塞型IO,通常称为New IO.这里只考虑到java.io包中堵塞型IO: 2. ...