数独就要DLX,不然不乐意。

数独的DLX构造:9*9个点每一个点有9种选择,这构成了DLX的729行,每行、列、阵有限制,均为9行(/列/阵),然后每行(/列/阵)都有九种数的情况。于是就有了3*9*9列。可是由于一个位置仅仅能选一个,所以又有9*9列,每列连接一个点的九种选数情况。

终于有4*9*9=324列,9*9*9=729行。

处理:

有些点已经有数了,可是这并不重要,我们仅仅须要给这个点加上一个行,为它已经选的数。而不要把9种情况都加上,这样在有精确覆盖的情况下(即有解),第四部分的某列在纵向就仅仅连接一个节点,显然这个节点是必选的,所以不会出错(当然你要是依旧给这个有值节点在DLX中加9行的话。那我也没招,不要问我为什么错,好吧你不会这么傻吧?)。

而其他没有初始值的数独点,自然就加旧行了没疑问吧?

说一个跟空间复杂度相关的事。就是一行有且仅有4个节点。分别在行、列、阵、位置这四部分的列中,那么总节点数(不算辅助节点)就应该最多是729*4。而实际上标准数独都是有唯一解的,所以须要的节点将远远小于这个数。

再说说时间复杂度:由于我们能够为DLX加一个优化。就是每次选一个列中节点最少的列继续DLX的过程,所以我们尽管保留了已经有值的节点,可是实际上最開始就选择了它们,而若数独有解。这也是必然选择的。所以并不会出现由于层数过多而导致回溯过度而TLE的情况,也就是说它还是非常快的。当然。强迫症神马的我也管不了。你要是乐意把已赋值点删掉我也不拦着,但不像上一篇代码了。你要这么写的话,我并不会给你提供代码支持。

事实上这么写最重要的原因就是:代。码!好!

写!

好吧,我把我好写好读的代码贴上来吧!提示:要读代码先看define!事实上这道题的define非常easy。并没有一些恶心人的for循环define,你要是认为读着恶心一定是你的问题了。

贴代码:

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define N 800
#define M 400
#define NN 5000
#define inf 0x3f3f3f3f #define Li_Sdk 3
#define Gi_Sdk 9
#define Su_Sdk 81
using namespace std;
char TS[N];
struct DLX
{
int elist,eline;
int id[Gi_Sdk+1][Gi_Sdk+1][Gi_Sdk+1];
int eid[4][Gi_Sdk][Gi_Sdk];
bool map[M][N]; int U[NN],D[NN],L[NN],R[NN],C[NN],V[NN];
int H[N],T[M],cnt;
int ans[NN];
bool visit[M],vist[M]; inline void init()
{
int i,j,k,_i,_j;
for(i=1;i<=Gi_Sdk;i++)
for(j=1;j<=Gi_Sdk;j++)
for(k=1;k<=Gi_Sdk;k++)
id[i][j][k]=++eline;
for(i=1;i<=Gi_Sdk;i++)/*行*/
{
for(j=1;j<=Gi_Sdk;j++)/*数*/
{
int A=eid[0][i][j]=++elist;
for(k=1;k<=Gi_Sdk;k++)/*列*/
{
int B=id[i][k][j];
map[A][B]=1;
}
}
}
for(i=1;i<=Gi_Sdk;i++)/*列*/
{
for(j=1;j<=Gi_Sdk;j++)/*数*/
{
int A=eid[1][i][j]=++elist;
for(k=1;k<=Gi_Sdk;k++)/*行*/
{
int B=id[k][i][j];
map[A][B]=1;
}
}
}
for(i=0;i<Li_Sdk;i++)for(j=0;j<Li_Sdk;j++)/*九宫格*/
{
for(k=1;k<=Gi_Sdk;k++)/*数*/
{
int A=eid[2][i*Li_Sdk+j+1][k]=++elist;
for(_i=1;_i<=Li_Sdk;_i++)for(_j=1;_j<=Li_Sdk;_j++)/*格内点*/
{
int B=id[i*Li_Sdk+_i][j*Li_Sdk+_j][k];
map[A][B]=1;
}
}
}
for(i=1;i<=Gi_Sdk;i++)for(j=1;j<=Gi_Sdk;j++)/*点的位置*/
{
int A=eid[3][i][j]=++elist;
for(k=1;k<=Gi_Sdk;k++)/*点的9个数*/
{
int B=id[i][j][k];
map[A][B]=1;
}
}
/* for(j=1;j<=eline;j++)
{
for(i=1;i<=elist;i++)
{
printf("%d",map[i][j]);
}
puts("");
}
*/ /*本题的数独是正常数独,所以有下面固定信息。*/
/*合计eline即DLX的行有9*9*9=729行,即每一个位置的九种数字选择。*/
/*合计elist即DLX的列有4*9*9=324列。即行、列、九宫格、位置的4种精确覆盖*/
}
inline void clear()
{
cnt=0;
memset(U,0,sizeof(U));
memset(D,0,sizeof(D));
memset(L,0,sizeof(L));
memset(R,0,sizeof(R));
memset(C,0,sizeof(C));
memset(H,0,sizeof(H));
memset(T,0,sizeof(T));
memset(ans,0,sizeof(ans));
memset(vist,0,sizeof(vist));
memset(visit,0,sizeof(visit));
}
inline void newnode(int x,int y)
{
C[++cnt]=y;V[cnt]=x;T[y]++; if(!H[x])H[x]=L[cnt]=R[cnt]=cnt;
else L[cnt]=H[x],R[cnt]=R[H[x]];
R[H[x]]=L[R[H[x]]]=cnt,H[x]=cnt; U[cnt]=U[y],D[cnt]=y;
U[y]=D[U[y]]=cnt;
}
inline void remove(int x)
{
for(int i=D[x];i!=x;i=D[i])
{
for(int j=R[i];j!=i;j=R[j])
{
U[D[j]]=U[j];
D[U[j]]=D[j];
T[C[j]]--;
}
}
L[R[x]]=L[x];
R[L[x]]=R[x];
}
inline void resume(int x)
{
for(int i=U[x];i!=x;i=U[i])
{
for(int j=L[i];j!=i;j=L[j])
{
U[D[j]]=j;
D[U[j]]=j;
T[C[j]]++;
}
}
L[R[x]]=x;
R[L[x]]=x;
}
inline void build()
{
clear();
int i,j,k;
cnt=4*Su_Sdk;
for(i=1;i<=cnt;i++)
{
U[i]=D[i]=i;
L[i]=L[0],R[i]=0;
L[0]=R[L[0]]=i;
}
for(i=0;i<Gi_Sdk;i++)for(j=0;j<Gi_Sdk;j++)
{
int get=i*Gi_Sdk+j;
int alp=TS[get]-'.';
if(!alp)
{
for(k=get*Gi_Sdk+1;k<=get*Gi_Sdk+Gi_Sdk;k++)
for(int temp=1;temp<=elist;temp++)
if(map[temp][k])newnode(k,temp);
}
else
{
k=get*Gi_Sdk+TS[get]-'0';
for(int temp=1;temp<=elist;temp++)
if(map[temp][k])newnode(k,temp);
}
}
}
inline bool dfs()
{
if(!R[0])return true;
int S=R[0],W=T[S],i,j;
for(i=R[S];i;i=R[i])if(T[i]<W)
{
W=T[i];
S=i;
}
remove(S);
for(i=D[S];i!=S;i=D[i])
{
ans[(V[i]-1)/9]=(V[i]-1)%9+1;
for(j=R[i];j!=i;j=R[j])remove(C[j]);
if(dfs())return true;
for(j=L[i];j!=i;j=L[j])resume(C[j]);
}
resume(S);
return false;
}
inline void ret(){for(int i=0;i<Su_Sdk;i++)printf("%d",ans[i]);}
}dlx;
int main()
{
// freopen("test.in","r",stdin);
// freopen("my.out","w",stdout);
int n,m;
dlx.init();
while(scanf("%s",TS),TS[0]!='e')
{
dlx.build();
dlx.dfs();
dlx.ret();
puts("");
}
// fclose(stdin);
// fclose(stdout);
return 0;
}

【POJ3074】Sudoku DLX(Dancing Links)的更多相关文章

  1. 【POJ3740】Easy Finding DLX(Dancing Links)精确覆盖问题

    题意:多组数据,每组数据给你几行数,要求选出当中几行.使得每一列都有且仅有一个1.询问是可不可行,或者说能不能找出来. 题解:1.暴搜.2.DLX(Dancing links). 本文写的是DLX. ...

  2. 跳跃的舞者,舞蹈链(Dancing Links)算法——求解精确覆盖问题

    精确覆盖问题的定义:给定一个由0-1组成的矩阵,是否能找到一个行的集合,使得集合中每一列都恰好包含一个1 例如:如下的矩阵 就包含了这样一个集合(第1.4.5行) 如何利用给定的矩阵求出相应的行的集合 ...

  3. [转] 舞蹈链(Dancing Links)——求解精确覆盖问题

    转载自:http://www.cnblogs.com/grenet/p/3145800.html 精确覆盖问题的定义:给定一个由0-1组成的矩阵,是否能找到一个行的集合,使得集合中每一列都恰好包含一个 ...

  4. 算法实践——舞蹈链(Dancing Links)算法求解数独

    在“跳跃的舞者,舞蹈链(Dancing Links)算法——求解精确覆盖问题”一文中介绍了舞蹈链(Dancing Links)算法求解精确覆盖问题. 本文介绍该算法的实际运用,利用舞蹈链(Dancin ...

  5. 转载 - 算法实践——舞蹈链(Dancing Links)算法求解数独

    出处:http://www.cnblogs.com/grenet/p/3163550.html 在“跳跃的舞者,舞蹈链(Dancing Links)算法——求解精确覆盖问题”一文中介绍了舞蹈链(Dan ...

  6. 转载 - 跳跃的舞者,舞蹈链(Dancing Links)算法——求解精确覆盖问题

    出处:http://www.cnblogs.com/grenet/p/3145800.html 精确覆盖问题的定义:给定一个由0-1组成的矩阵,是否能找到一个行的集合,使得集合中每一列都恰好包含一个1 ...

  7. 算法帖——用舞蹈链算法(Dancing Links)求解俄罗斯方块覆盖问题

    问题的提出:如下图,用13块俄罗斯方块覆盖8*8的正方形.如何用计算机求解? 解决这类问题的方法不一而足,然而核心思想都是穷举法,不同的方法仅仅是对穷举法进行了优化 用13块不同形状的俄罗斯方块(每个 ...

  8. 洛谷P3369 【模板】普通平衡树(Treap/SBT)

    洛谷P3369 [模板]普通平衡树(Treap/SBT) 平衡树,一种其妙的数据结构 题目传送门 题目描述 您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作: 插入x数 删除 ...

  9. 【CF235C】Cyclical Quest(后缀自动机)

    [CF235C]Cyclical Quest(后缀自动机) 题面 洛谷 题解 大致翻译: 给定一个串 然后若干组询问 每次也给定一个串 这个串可以旋转(就是把最后一位丢到最前面这样子) 问这个串以及其 ...

随机推荐

  1. Javascript DOM 编程艺术(第二版)读书笔记——基本语法

    Javascript DOM 编程艺术(第二版),英Jeremy Keith.加Jeffrey Sambells著,杨涛.王建桥等译,人民邮电出版社. 学到这的时候,我发现一个问题:学习过程中,相当一 ...

  2. MySql IFNULL 联表查询出来的null 如何赋值

    mysql中isnull,ifnull,nullif的用法如下: isnull(expr) 的用法:如expr 为null,那么isnull() 的返回值为 1,否则返回值为 0.mysql> ...

  3. POJ_1050_(dp)

    To the Max Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 48232   Accepted: 25534 Desc ...

  4. Swift mutating Equatable Hashable 待研究

    Swift mutating Equatable Hashable 待研究

  5. 踩过好多次的坑 - ajax访问【mango】项目的service

    这个坑真的是踩过好多次了,好记性不如烂笔头,我总是太高估我的记忆力,这次真的是要写下来了. 项目是用的seam框架 + hibernate搭建的,架构是前辈们搭好的劳动成果,在配置service的访问 ...

  6. 【前端路由】Vue-router 中hash模式和history模式的区别

    咱们今天说说VUE路由的hash模式与history模式的区别,这个也是面试常问的问题,不要小看这道题其实问到这里的时候那个面试官应该是个大牛,开发经验丰富,这个题其实就是考验你的开发经验是否属实. ...

  7. CAD使用GetxDataDouble读数据(网页版)

    主要用到函数说明: MxDrawEntity::GetxDataDouble2 读取一个Double扩展数据,详细说明如下: 参数 说明 [in] LONG lItem 该值所在位置 [out, re ...

  8. 如何快速的vue init 属于自己的vue模板?

    相信很多接触过vue的小伙伴非常熟悉了,我们在开启项目之前都需要vue init webpack xx来初始化自己的项目目录.但是在实际开发中我们往往会根据公司要求或者业务的需要会对目录进行局部的调整 ...

  9. [转]SAS盘和SATA盘之间的区别

    很多人一提到SAS盘和SATA盘之后,首先想到的是接口方面的区别,SAS的接口速度比SATA高很多,所以认为SAS盘要比SATA盘快,性能高.其实,接口方面的区别并不是主要的,只是很小的一方面.那么, ...

  10. TWaver MONO模板库新鲜出炉 精彩纷呈

    MONO Design在线3D建模平台网站, www.mono-design.cn,开发组的成员们已经开始紧锣密鼓的对这个平台进行内测.在之前的文章里,我们提到用户可以获得多种多样的TWaver官方模 ...