poj 3074
题意:解数独
分析:
完整的数独有四个充要条件:
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的更多相关文章
- POJ 3074 Sudoku (DLX)
Sudoku Time Limit:1000MS Memory Limit:65536KB 64bit IO Format:%I64d & %I64u Submit Statu ...
- 搜索(DLX): POJ 3074 3076 Sudoku
POJ 3074 : Description In the game of Sudoku, you are given a large 9 × 9 grid divided into smaller ...
- POJ 3074 Sudoku (Dancing Links)
传送门:http://poj.org/problem?id=3074 DLX 数独的9*9的模板题. 具体建模详见下面这篇论文.其中9*9的数独怎么转化到精确覆盖问题,以及相关矩阵行列的定义都在下文中 ...
- 【POJ 3074】 Sudoku
[题目链接] http://poj.org/problem?id=3074 [算法] 将数独问题转化为精确覆盖问题,用Dancing Links求解 转化方法如下 : 我们知道,在一个数独中 : 1. ...
- DLX (poj 3074)
题目:Sudoku 匪夷所思的方法,匪夷所思的速度!!! https://github.com/ttlast/ACM/blob/master/Dancing%20Link%20DLX/poj%2030 ...
- POJ 3074 Sudoku DLX精确覆盖
DLX精确覆盖.....模版题 Sudoku Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 8336 Accepted: ...
- POJ 3074 Sudoku (Dacing Links)
推荐一个写数独很好的博客:http://www.cnblogs.com/grenet/p/3163550.html 主要是把九宫格里的元素换到矩阵里面再求解dancing links 网上找的一模版 ...
- poj 3074 Sudoku(Dancing Links)
Sudoku Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 8152 Accepted: 2862 Descriptio ...
- (简单) POJ 3074 Sudoku, DLX+精确覆盖。
Description In the game of Sudoku, you are given a large 9 × 9 grid divided into smaller 3 × 3 subgr ...
- POJ 3074 Sudoku(算竞进阶习题)
二进制优化+dfs 话说这题数据中真的丧心病狂..不加inline还过不去.. 因为不会DLX只好用二进制来优化了...万万没想到还是低空飘过 我们在行.列.格分别用一个9位二进制常数来记录什么数能放 ...
随机推荐
- 浅谈算法——splay
BST(二叉查找树)是个有意思的东西,种类巨TM多,然后我们今天不讲其他的,我们今天就讲splay 首先,如果你不知道Splay是啥,你也得知道BST是啥 如上图就是一棵优美的BST,它对于每个点保证 ...
- Poj 1236 Network of Schools (Tarjan)
题目链接: Poj 1236 Network of Schools 题目描述: 有n个学校,学校之间有一些单向的用来发射无线电的线路,当一个学校得到网络可以通过线路向其他学校传输网络,1:至少分配几个 ...
- 震惊!double输入输出的秘密竟然是~
遇到了一个神奇的事情: double r = 3.0; printf("%lf", r);//0.000000 double遇到printf函数竟然是用%f输出的! scanf函数 ...
- Spring.Net学习笔记(3)-创建对象
一.开发环境 编译器:VS2013 .Net版本:.net framework4.5 二.涉及程序集 Spring.Core.dll:1.3 Common.Logging 三.开发过程 1.项目结构 ...
- SQL传入时间获取到时间的周一和周日
declare @time datetime declare @timeMonday datetime set @time='2013-11-07' ) ,@time) select @timeMon ...
- ubuntu查看系统资源占用(内存,cpu和进程)
http://blog.csdn.net/vivian187/article/details/51476043 http://bluexp29.blog.163.com/blog/static/338 ...
- UVM基础之------uvm_port_base
Port Base Classes uvm_port_component_base This class defines an interface for obtaining a port ...
- [Windows Server 2003] 手工创建安全网站
★ 欢迎来到[护卫神·V课堂],网站地址:http://v.huweishen.com★ 护卫神·V课堂 是护卫神旗下专业提供服务器教学视频的网站,每周更新视频.★ 本节我们将带领大家:手工创建安全站 ...
- 世界上最受欢迎的10个Linux发行版
帮助新的Linux用户在越来越多的Linux发行版中选择最合适的操作系统,是创建这个网页的原因.它列出了迄今为止最流行的10个Linux发行版(另外增加的是FreeBSD,到目前为止最为流行的BSD系 ...
- MFC_2.5 选项卡控件的使用
选项卡控件的使用 1.新建默认MFC文件. 2.资源-添加Dialog-添加类.(假设生成3个,Dialog1Dialog2Dialog3) 3.类向导,添加类,点小三角形,添加MFC类.添加CTab ...