题意:解数独

分析:

完整的数独有四个充要条件:

1.每个格子都有填数字

2.每列都有1~9中的每个数字

3.每行都有1~9中的每个数字

4.每个9宫格都有1~9中的每个数字

可以转化成精确覆盖问题。每行表示一个格子的一种填法,1~81列表示这个格子的位置,82~162列表示这是哪一行的什么数字,163~243列表示这是哪一列的什么数字,244~324列表示这是哪一个九宫格里的什么数字。每行都把四个1填入这四个区间里的对应位置。最后求出这个01矩阵的精确覆盖就是解。

在DFS里删除列的顺序为由左往右时TLE了,由右向左却AC,什么原因???

 #include <cstdio>
#include <cstring>
int U[],D[],L[],R[],row[],col[],cont[];
int X[],Y[],H[],S[],M,N,sz,ans[][];
bool hashr[][],hashc[][],hashp[][];
void init(int m)
{
for(int i = ;i <= m;i++)
{
U[i] = D[i] = i;
L[i + ] = i;
R[i] = i + ;
S[i] = ;
}
R[m] = ;
L[] = m;
sz = m + ;
} void remove(int c)
{
//删除一整列
R[L[c]] = R[c];
L[R[c]] = L[c];
//删除行
for(int i = D[c];i != c;i = D[i])
{
for(int j = R[i];j != i;j = R[j])
{
D[U[j]] = D[j];
U[D[j]] = U[j];
S[X[j]]--;
}
}
} void resume(int c)
{
//恢复一整列
L[R[c]] = c;
R[L[c]] = c;
//恢复行
for(int i = U[c];i != c;i = U[i])
{
for(int j = L[i];j != i;j = L[j])
{
D[U[j]] = j;
U[D[j]] = j;
S[X[j]]++;
}
}
} void ins(int r,int c)
{
S[c]++;
//纵向插入
D[U[c]] = sz;
U[sz] = U[c];
D[sz] = c;
U[c] = sz;
X[sz] = c;
Y[sz] = r;
//横向插入
if(H[r] == -)
{
H[r] = L[sz] = R[sz] = sz;
}
else
{
R[L[H[r]]] = sz;
L[sz] = L[H[r]];
R[sz] = H[r];
L[H[r]] = sz;
}
sz++;
} bool dfs(int k)
{
if(R[] == )
{
return true;
}
else
{
int m = 0xfffffff,num;
for(int i = R[];i != ;i = R[i])
{
if(S[i] == )
{
return false;
}
if(m > S[i])
{
m = S[i];
num = i;
if(m == )
{
break;
}
}
}
remove(num);
for(int i = D[num];i != num;i = D[i])
{
ans[row[Y[i]]][col[Y[i]]] = cont[Y[i]];
for(int j = R[i];j != i;j = R[j])
{
remove(X[j]);
}
if(dfs(k + ))
{
return true;
}
for(int j = L[i];j != i;j = L[j])//恢复顺序改为由左向右居然慢N倍?!
{
resume(X[j]);
}
}
resume(num);
}
return false;
} int main()
{
char input[];
while(scanf("%s",input),input[] != 'e')
{
memset(hashr,false,sizeof(hashr));
memset(hashc,false,sizeof(hashc));
memset(hashp,false,sizeof(hashp));
for(int i = ;i < ;i++)
{
for(int j = ;j < ;j++)
{
if(input[i * + j] != '.')
{
hashr[i][input[i * + j] - ''] = true;
hashc[j][input[i * + j] - ''] = true;
hashp[i / * + j / ][input[i * + j] - ''] = true;
}
}
}
M = * * ;
N = ;
init(M);
for(int i = ;i < ;i++)
{
for(int j = ;j < ;j++)
{
int k;
if(input[i * + j] != '.')
{
k = input[i * + j] - '';
}
else
{
k = ;
}
if(k != )
{
row[N] = i;
col[N] = j;
cont[N] = k;
H[N] = -;
ins(N,i * + j + );//(i,j)位置已填数字
ins(N, + i * + k);//i行已有k
ins(N, + j * + k);//j列已有k
ins(N++, + (i / * + j / ) * + k);//宫格已有k
}
else
{
for(k = ;k <= ;k++)
{
if(!hashr[i][k] && !hashc[j][k] && !hashp[i / * + j / ][k])
{
row[N] = i;
col[N] = j;
cont[N] = k;
H[N] = -;
ins(N,i * + j + );//(i,j)位置已填数字
ins(N, + i * + k);//i行已有k
ins(N, + j * + k);//j列已有k
ins(N++, + (i / * + j / ) * + k);//宫格已有k
}
}
}
}
}
dfs();
for(int i = ;i < ;i++)
{
for(int j = ;j < ;j++)
{
printf("%d",ans[i][j]);
}
}
printf("\n");
}
return ;
}

poj 3074的更多相关文章

  1. POJ 3074 Sudoku (DLX)

    Sudoku Time Limit:1000MS     Memory Limit:65536KB     64bit IO Format:%I64d & %I64u Submit Statu ...

  2. 搜索(DLX): POJ 3074 3076 Sudoku

    POJ 3074 : Description In the game of Sudoku, you are given a large 9 × 9 grid divided into smaller ...

  3. POJ 3074 Sudoku (Dancing Links)

    传送门:http://poj.org/problem?id=3074 DLX 数独的9*9的模板题. 具体建模详见下面这篇论文.其中9*9的数独怎么转化到精确覆盖问题,以及相关矩阵行列的定义都在下文中 ...

  4. 【POJ 3074】 Sudoku

    [题目链接] http://poj.org/problem?id=3074 [算法] 将数独问题转化为精确覆盖问题,用Dancing Links求解 转化方法如下 : 我们知道,在一个数独中 : 1. ...

  5. DLX (poj 3074)

    题目:Sudoku 匪夷所思的方法,匪夷所思的速度!!! https://github.com/ttlast/ACM/blob/master/Dancing%20Link%20DLX/poj%2030 ...

  6. POJ 3074 Sudoku DLX精确覆盖

    DLX精确覆盖.....模版题 Sudoku Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 8336   Accepted: ...

  7. POJ 3074 Sudoku (Dacing Links)

    推荐一个写数独很好的博客:http://www.cnblogs.com/grenet/p/3163550.html 主要是把九宫格里的元素换到矩阵里面再求解dancing links 网上找的一模版 ...

  8. poj 3074 Sudoku(Dancing Links)

    Sudoku Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 8152   Accepted: 2862 Descriptio ...

  9. (简单) POJ 3074 Sudoku, DLX+精确覆盖。

    Description In the game of Sudoku, you are given a large 9 × 9 grid divided into smaller 3 × 3 subgr ...

  10. POJ 3074 Sudoku(算竞进阶习题)

    二进制优化+dfs 话说这题数据中真的丧心病狂..不加inline还过不去.. 因为不会DLX只好用二进制来优化了...万万没想到还是低空飘过 我们在行.列.格分别用一个9位二进制常数来记录什么数能放 ...

随机推荐

  1. goalng——time包学习

    1.星期:type Weekday int const ( Sunday Weekday = iota Monday Tuesday Wednesday Thursday Friday Saturda ...

  2. (DP)51NOD 1118 机器人走方格

    M * N的方格,一个机器人从左上走到右下,只能向右或向下走.有多少种不同的走法?由于方法数量可能很大,只需要输出Mod 10^9 + 7的结果. Input 第1行,2个数M,N,中间用空格隔开.( ...

  3. 【Tair】淘宝分布式NOSQL框架:Tair

    Tair是淘宝的一个开源项目,它是一个分布式的key/value结构数据的解决方案. 一.基本组成 作为一个分布式系统,Tair由一个中心控制节点(config server)和一系列的服务节点(da ...

  4. UE编辑器编译和运行java设置

    工具原料: UE编辑器 1点击“高级”,再点击“工具配置”. 2点击“插入”,在“菜单项”名称上输入“编译java程序”,在“命令行”里输入“javac %n%e”,在工作目录上填“%p”. 3切换到 ...

  5. AOP面向方面编程---postsharp

    PostSharp是一个用于在.NET平台上实现AOP(Aspect-Oriented Programming,面向方面编程)的框架,现通过简单的示例代码来演示如何使用postsharp. 1.新建一 ...

  6. SVN服务器搭建 内网可用外网不可用的问题

    检查1:内网端口映射到了外网端口,这样外网才能够访问到 映射的方式有两种: 1.通过路由器的虚拟服务器功能,网上一搜一大把. 2.将路由器的DMZ功能开启,并把DMZ主机设置为目标计算机. 检查2:S ...

  7. JSP&&EL&&JSTL

    JSP = JAVA + HTML + JSP自身的东西 JSP的脚本         <%!   %>        :翻译成Servlet中的成员内容. 定义变量,方法,类. -- ...

  8. es6 export-from用法

    语法: export * from "foo"; export {foo} from "foo"; export {foo, bar} from "f ...

  9. CF842C Ilya And The Tree

    思路: 1. 如果根节点是0,那么可以通过一次dfs计算出所有节点的最大值. 2. 如果根节点不是0,那么其余各点的最大值一定是根节点的一个因子.首先计算出根节点的所有因子.在dfs到一个深度为d的节 ...

  10. bash 博弈

    转载并修改自: http://www.cnblogs.com/wulangzhou/archive/2013/03/14/2959660.html 简单的取拿游戏一堆石子(或者其它的什么东西),下面是 ...