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

Description

In the game of Sudoku, you are given a large 9 × 9 grid divided into smaller 3 × 3 subgrids. For example,

. 2 7 3 8 . . 1 .
. 1 . . . 6 7 3 5
. . . . . . . 2 9
3 . 5 6 9 2 . 8 .
. . . . . . . . .
. 6 . 1 7 4 5 . 3
6 4 . . . . . . .
9 5 1 8 . . . 7 .
. 8 . . 6 5 3 4 .

Given some of the numbers in the grid, your goal is to determine the remaining numbers such that the numbers 1 through 9 appear exactly once in (1) each of nine 3 × 3 subgrids, (2) each of the nine rows, and (3) each of the nine columns.

Input

The input test file will contain multiple cases. Each test case consists of a single line containing 81 characters, which represent the 81 squares of the Sudoku grid, given one row at a time. Each character is either a digit (from 1 to 9) or a period (used
to indicate an unfilled square). You may assume that each puzzle in the input will have exactly one solution. The end-of-file is denoted by a single line containing the word “end”.

Output

For each test case, print a line representing the completed Sudoku puzzle.

Sample Input

.2738..1..1...6735.......293.5692.8...........6.1745.364.......9518...7..8..6534.
......52..8.4......3...9...5.1...6..2..7........3.....6...1..........7.4.......3.
end

Sample Output

527389416819426735436751829375692184194538267268174593643217958951843672782965341
416837529982465371735129468571298643293746185864351297647913852359682714128574936

Source

题意:

就是经典的数独问题。

思路:

搜索。

可是得借助Dancing Links加速。关键就在于如何把数独问题抽象成一个精确覆盖问题了。

我们首先考虑数独的游戏规则。

1.每一个格子都必须填一个数字。

2.每一行1-9这几个数字都必须出现一次。

3.每一列1-9这几个数字都必须出现一次。

4.每一宫格1-9这几个数字都必须出现一次。

我们知道Dancing Links的精确覆盖智能处理0,1的序列覆盖每一列为一个约束条件。

那么我们就必须把上述约束转换成0,1矩阵。

对于1。

我们用第(i-1)*9+j列为1表示i行j列的已经填数。一共占用81列。

对于2.我们用81+(i-1)*9+v列表示第i行已经有v这个值。一共占用81列。

对于3.我们用162+(j-1)*9+v列表示第j列已经有v这个值。一共占用81列。

对于3.我们用243+(3*((i-1)/3)+(j+2)/3-1)+v列表示第3*((i-1)/3)+(j+2)/3宫格已经有v这个值。一共占用81列。

ps:i,j都从1開始。3*((i-1)/3)+(j+2)/3为通过i,j确定的宫格数。

这样就会为每一个宫格确定一个01序列约束。

然后建好矩阵后。

套上精确覆盖模板后就ok了。

具体见代码:

#include<iostream>
#include<stdio.h>
#include<string.h>
using namespace std;
const int INF=0x3f3f3f3f;const int maxn=3645;//每一个格子可能有9个取值。 所以最多有81*9行。然后243列。 int U[maxn],D[maxn],L[maxn],R[maxn],C[maxn],row[maxn];//上下左右指针。c[i]结点i相应的列。row[i]结点i相应的行号。 int S[350],H[800],ans[100];//S[i]为i列1的个数。 H[i]为i行的尾指针。 int n,m,cnt,deep;
struct node
{
int x,y,v;
} st[maxn];
char maze[150],path[150];
void init()
{
int i;
for(i=1;i<=800;i++)
H[i]=-1;
for(i=0;i<=324;i++)
{
S[i]=0;
L[i+1]=i;
R[i]=i+1;
U[i]=D[i]=i;
}
R[324]=deep=0;
cnt=325;
}
void Insert(int r,int c)
{
//头插法建链表
U[cnt]=c,D[cnt]=D[c];//确定新增结点上下指针信息
U[D[c]]=cnt,D[c]=cnt;//恢复链表信息
if(H[r]==-1) //确定左右指针信息
H[r]=L[cnt]=R[cnt]=cnt;//增加头
else
{
L[cnt]=H[r],R[cnt]=R[H[r]];//头插法
L[R[H[r]]]=cnt,R[H[r]]=cnt;
}
S[c]++;//更新附加信息
row[cnt]=r;
C[cnt++]=c;
}
void Remove(int c)//移除c列。
{
int i,j;
R[L[c]]=R[c],L[R[c]]=L[c];
for(i=D[c];i!=c;i=D[i])
for(j=R[i];j!=i;j=R[j])
D[U[j]]=D[j],U[D[j]]=U[j],S[C[j]]--;
}
void Resume(int c)//还原c列。
{
int i,j;
R[L[c]]=L[R[c]]=c;
for(i=D[c];i!=c;i=D[i])
for(j=R[i];j!=i;j=R[j])
D[U[j]]=U[D[j]]=j,S[C[j]]++;
}
bool dfs()
{
if(R[0]==0)
return true;
int i,j,c,miv=INF;
for(i=R[0];i;i=R[i])
if(S[i]<miv)
miv=S[i],c=i;
Remove(c);//处理第c列
for(i=D[c];i!=c;i=D[i])
{
for(j=R[i];j!=i;j=R[j])
Remove(C[j]);
ans[deep++]=row[i];
if(dfs())
return true;
for(j=L[i];j!=i;j=L[j])
Resume(C[j]);
deep--;
}
Resume(c);
return false;
}
int main()
{
int i,j,v,r,p;
while(gets(maze))
{
if(maze[0]=='e')
break;
init();
r=1;
for(i=1;i<=9;i++)//每行为一个格子的一种选择。 {
for(j=1;j<=9;j++)
{
if(maze[(i-1)*9+j-1]=='.')
{
for(v=1;v<=9;v++)
{
Insert(r,(i-1)*9+j);
Insert(r,81+(i-1)*9+v);
Insert(r,162+(j-1)*9+v);
Insert(r,243+(((i-1)/3)*3+(j+2)/3-1)*9+v);
st[r].x=i,st[r].y=j,st[r].v=v;
r++;
}
}
else
{
v=maze[(i-1)*9+j-1]-'0';
Insert(r,(i-1)*9+j);
Insert(r,81+(i-1)*9+v);
Insert(r,162+(j-1)*9+v);
Insert(r,243+(((i-1)/3)*3+(j+2)/3-1)*9+v);
st[r].x=i,st[r].y=j,st[r].v=v;
r++;
}
}
}
dfs();
for(i=0;i<deep;i++)
{
p=ans[i];
path[(st[p].x-1)*9+st[p].y-1]='0'+st[p].v;
}
path[deep]=0;
printf("%s\n",path);
}
return 0;
}

版权声明:本文博主原创文章。博客,未经同意不得转载。

poj 3074 Sudoku(Dancing Links)的更多相关文章

  1. POJ 3074 Sudoku (Dacing Links)

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

  2. POJ 3076 Sudoku (dancing links)

    题目大意: 16*16的数独. 思路分析: 多说无益. 想说的就是dancing links 的行是依照 第一行第一列填 1 第一行第二列填 2 -- 第一行第十五列填15 第一行第二列填 1 -- ...

  3. POJ 3074 Sudoku (Dancing Links)

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

  4. POJ 3074 Sudoku (DLX)

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

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

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

  6. POJ 3074 Sudoku DLX精确覆盖

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

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

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

  8. POJ - 3074 Sudoku (搜索)剪枝+位运算优化

    In the game of Sudoku, you are given a large 9 × 9 grid divided into smaller 3 × 3 subgrids. For exa ...

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

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

随机推荐

  1. 【VB/.NET】Converting VB6 to VB.NET 【Part II】【之四】

    第四部分 原文 DLLs, DAO, RDO, ADO, and AD.NET; the History of VB DBs In the early versions of VB, there we ...

  2. 对Kalman(卡尔曼)滤波器的理解

    1.简单介绍(Brief Introduction) 在学习卡尔曼滤波器之前,首先看看为什么叫"卡尔曼". 跟其它著名的理论(比如傅立叶变换.泰勒级数等等)一样.卡尔曼也是一个人的 ...

  3. IBM之MQ使用指南

    随着计算机网络和分布式应用的不断发展.远程消息传递越来越成为应用系统中必不可少的组成部分. 商业消息中间件的出现保证了消息传输的可靠性,高效率和安全性,同一时候也降低了系统的开发周期. 眼下应用最多的 ...

  4. 对付"反盗链"

    对付"反盗链" 某些站点有所谓的反盗链设置,其实说穿了很简单, 就是检查你发送请求的header里面,referer站点是不是他自己, 所以我们只需要像把headers的refer ...

  5. hdu1081(最大子矩阵)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1081 分析:a[i][j]代表第i行,前j个数据的和:那么由a[i][j]可得sum[k][long] ...

  6. Visual Studio使用正则表达式快速统计总共代码行数

    原文:Visual Studio使用正则表达式快速统计总共代码行数 按CTRL+SHIFT+F,勾上支持正则表达式,然后输入搜索内容: <span style="font-family ...

  7. java 调用mysql的存储过程(简单示例)

    首先我在mysql的test数据库里定义了一个student表: create table student4( id   int   primary key, sanme char(5) ); 插入几 ...

  8. Mina框架断包、粘包问题解决方式

    Mina框架断包.粘包问题解决方式 Apache Mina Server 是一个网络通信应用框架,也就是说,它主要是对基于TCP/IP.UDP/IP协议栈的通信框架(当然.也能够提供JAVA 对象的序 ...

  9. EJB体系结构

    为了适应企业的快速发展.缩短企业信息系统的设计和开发周期.降低构建信息系统的成本,Sun公司制订了Java2 SDK Enterprise Edition(J2EE)规范,定义基于组件的方式设计.开发 ...

  10. SQL SERVER IN参数化处理

    方法一. CREATE TABLE [dbo].[Users] ( Id INTEGER IDENTITY(1, 1) PRIMARY KEY , Name NVARCHAR(50) NOT NULL ...