HDU 3111 Sudoku ( Dancing Links 精确覆盖模型 )
推荐两篇学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 精确覆盖模型 )的更多相关文章
- POJ3074 Sudoku —— Dancing Links 精确覆盖
题目链接:http://poj.org/problem?id=3074 Sudoku Time Limit: 1000MS Memory Limit: 65536K Total Submissio ...
- HDU 2295 Radar (二分 + Dancing Links 重复覆盖模型 )
以下转自 这里 : 最小支配集问题:二分枚举最小距离,判断可行性.可行性即重复覆盖模型,DLX解之. A*的启发函数: 对当前矩阵来说,选择一个未被控制的列,很明显该列最少需要1个行来控制,所以ans ...
- 【转】Dancing Links精确覆盖问题
原文链接:http://sqybi.com/works/dlxcn/ (只转载过来一部分,全文请看原文,感觉讲得很好~)正文 精确覆盖问题 解决精确覆盖问题 舞蹈步骤 效率分析 ...
- HDU 2295 Radar dancing links 重复覆盖
就是dancing links 求最小支配集,重复覆盖 精确覆盖时:每次缓存数据的时候,既删除行又删除列(这里的删除列,只是删除表头) 重复覆盖的时候:只删除列,因为可以重复覆盖 然后重复覆盖有一个估 ...
- hihoCoder #1321 : 搜索五•数独 (Dancing Links ,精确覆盖)
hiho一下第102周的题目. 原题地址:http://hihocoder.com/problemset/problem/1321 题意:输入一个9*9数独矩阵,0表示没填的空位,输出这个数独的答案. ...
- hust 1017 dancing links 精确覆盖模板题
最基础的dancing links的精确覆盖题目 #include <iostream> #include <cstring> #include <cstdio> ...
- ZOJ 3209 Treasure Map (Dancing Links 精确覆盖 )
题意 : 给你一个大小为 n * m 的矩形 , 坐标是( 0 , 0 ) ~ ( n , m ) .然后给你 p 个小矩形 . 坐标是( x1 , y1 ) ~ ( x2 , y2 ) , 你选 ...
- HDU 3335 Divisibility dancing links 重复覆盖
分析: dlx重复覆盖的巧用,重复覆盖的原理恰好符合本题的筛选方式,即选择一个数后,该数的倍数或约数可以保证在之后的搜索中不会被选择 于是修改一下启发函数,求解最大的重复覆盖即可. 其实不一定不被 ...
- HDU 5046 Airport ( Dancing Links 反复覆盖 )
今年上海网络赛的一道题目 , 跟 HDU 2295 如出一辙 . 就是距离的计算一个是欧几里得距离 , 一个是曼哈顿距离 学完DLX感觉这题好水 ,就是一个裸的反复覆盖 注意下别溢出即可了 #incl ...
随机推荐
- xml中${}的使用含义(美元符号大括号,以Spring、ibatis、mybatis为例)
项目中,经常会在xml中看到这样的写法: <properties resource="properties/database.properties"/> <dat ...
- 动态生成的DOM做点击事件无效
有时候我们的标签都是从后台获取的数据,然后利用JS添加到页面上,当我们写生成的标签的点击事件(click)时没有效果. 例如: <section> 测试动态生成的DOM点击事件 <b ...
- java基础 File与递归练习 使用文件过滤器筛选将指定文件夹下的小于200K的小文件获取并打印按层次打印(包括所有子文件夹的文件) 多层文件夹情况统计文件和文件夹的数量 统计已知类型的数量 未知类型的数量
package com.swift.kuozhan; import java.io.File; import java.io.FileFilter; /*使用文件过滤器筛选将指定文件夹下的小于200K ...
- JavaScript中并非一切皆对象
对象是js中的基础以及核心,在js中有六种主要类型:string number boolean null undefined object 除了oject类型以为其他五种本身并非对象,null本身 ...
- 基于asp.net MVC 的服务器和客户端的交互(一)
架构思想 三层架构 提出了一种基于ASP.NET开发方式的三层架构的Web应用系统构造思想.其基本内容是:将面向对象的UML建模与Web应用系统开发 相结合,将整个系统分成适合ASP.NET开发方式的 ...
- JQuery实现父级选择器(广告实现)
效果图如下: HTML代码如下: <!DOCTYPE html> <html lang="en"> <head> <meta charse ...
- JS提示Cannot read property 'replace' of undefined
出现这个错误的原因一般是传的参数为null 在传参之前加个是否为null的判断就行了.
- ayui弹出层闪退,layer弹出层闪退,layer弹出层坑
今天用layui的弹出层插件,发现两奇怪的问题: 1.弹窗打开事件还未绑定到任何按钮,可是点击form表单中的按钮可以打开我定义的弹出层 2.绑定弹出层到按钮,打开弹窗闪退 后面发现真如参考博文所说: ...
- 类的特殊方法"__call__"详解
1. __call__ 当执行对象名+括号时, 会自动执行类中的"__call__"方法, 怎么用? class A: def __init__(self, name): self ...
- 【Python 2 到 3 系列】 关于除法的余数
v2.2 以前,除("/")运算符的返回有两种可能情况,分别是整型和浮点型.操作数的不同,是影响计算结果数据类型的关键. 以 a / b 为例,a.b均为整型,则结果返回整型:a. ...