题目链接:http://poj.org/problem?id=3074

Sudoku
Time Limit: 1000MS   Memory Limit: 65536K
Total Submissions: 10451   Accepted: 3776

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博客(来自万仓一黍 )

Dancing Links的一些特点:

1.矩阵中每个元素的值只能是0或1(在实际操作中只记录1)。

2.行代表着放置情况, 列代表着约束条件。其中矩阵中的行和列的编号从1开始。

3.选择若干行,使得其满足所有约束条件。

对于此题:

1.行:9*9*9,表明有9*9个格子,每个格子有9中情况。

2.列:9*9*4,首先每个格子能且仅能放1个数字,其次每一行的九个数字能且仅能被放一次, 再者列如行者,最后每个九宫格的九个数字能且仅能被放一次。

3.所以构成了(9*9*9) * (9*9*4)的矩阵,然后直接套模板。

代码如下:

 #include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <vector>
#include <queue>
#include <stack>
#include <map>
#include <string>
#include <set>
#define ms(a,b) memset((a),(b),sizeof((a)))
using namespace std;
typedef long long LL;
const int N = ;
const int MaxN = N*N*N+;
const int MaxM = N*N*+;
const int maxnode = MaxN* + MaxM + ; char g[MaxN];
struct DLX //矩阵的行和列是从1开始的
{
int n, m, size; //size为结点数
int U[maxnode], D[maxnode], L[maxnode], R[maxnode], Row[maxnode], Col[maxnode];
int H[MaxN], S[MaxM]; //H为每一行的头结点,但不参与循环。S为每一列的结点个数
int ansd, ans[MaxN]; void init(int _n, int _m) //m为列
{
n = _n;
m = _m;
for(int i = ; i<=m; i++) //初始化列的头结点
{
S[i] = ;
U[i] = D[i] = i;
L[i] = i-;
R[i] = i+;
}
R[m] = ; L[] = m;
size = m;
for(int i = ; i<=n; i++) H[i] = -; //初始化行的头结点
} void Link(int r, int c)
{
size++; //类似于前向星
Col[size] = c;
Row[size] = r;
S[Col[size]]++;
D[size] = D[c];
U[D[c]] = size;
U[size] = c;
D[c] = size;
if(H[r]==-) H[r] = L[size] = R[size] = size; //当前行为空
else //当前行不为空: 头插法,无所谓顺序,因为Row、Col已经记录了位置
{
R[size] = R[H[r]];
L[R[H[r]]] = size;
L[size] = H[r];
R[H[r]] = size;
}
} void remove(int c) //c是列的编号, 不是结点的编号
{
L[R[c]] = L[c]; R[L[c]] = R[c]; //在列的头结点的循环队列中, 越过列c
for(int i = D[c]; i!=c; i = D[i])
for(int j = R[i]; j!=i; j = R[j])
{
//被删除结点的上下结点仍然有记录
U[D[j]] = U[j];
D[U[j]] = D[j];
S[Col[j]]--;
}
} void resume(int c)
{
L[R[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])
{
U[D[j]] = D[U[j]] = j;
S[Col[j]]++;
}
} bool Dance(int d)
{
if(R[]==)
{
for(int i = ; i<d; i++) g[(ans[i]-)/] = (ans[i]-)% + '';
for(int i = ; i<N*N; i++) printf("%c", g[i]);
printf("\n");
return true;
} int c = R[];
for(int i = R[]; i!=; i = R[i]) //挑结点数最少的那一列,否则会超时,那为什么呢?
if(S[i]<S[c])
c = i; remove(c);
for(int i = D[c]; i!=c; i = D[i])
{
ans[d] = Row[i];
for(int j = R[i]; j!=i; j = R[j]) remove(Col[j]);
if(Dance(d+)) return true;
for(int j = L[i]; j!=i; j = L[j]) resume(Col[j]);
}
resume(c);
return false;
}
}; //i、j从0开始,代表着位置; k从1开始,代表着数字
void place(int &r, int &c1, int &c2,int &c3, int &c4, int i, int j, int k)
{
//c1为每个格子一个数, c2为行, c3为列, c4为九宫格
r = (i*N+j)*N+k; c1 = i*N+j+; c2 = N*N+i*N+k;
c3 = N*N*+j*N+k; c4 = N*N*+((i/)*+(j/))*N+k;
} DLX dlx;
int main()
{
while(scanf("%s", g) && strcmp(g,"end") )
{
dlx.init(N*N*N, N*N*);
int r, c1, c2, c3,c4;
for(int i = ; i<N; i++)
for(int j = ; j<N; j++)
for(int k = ; k<=N; k++)
if(g[i*N+j]=='.' || g[i*N+j]==''+k)
{
place(r,c1,c2,c3,c4,i,j,k); //获取位置
dlx.Link(r,c1); //加入到矩阵中, 下同
dlx.Link(r,c2);
dlx.Link(r,c3);
dlx.Link(r,c4);
}
dlx.Dance(); //一起摇摆
}
return ;
}

POJ3074 Sudoku —— Dancing Links 精确覆盖的更多相关文章

  1. HDU 3111 Sudoku ( Dancing Links 精确覆盖模型 )

    推荐两篇学DLX的博文: http://bbs.9ria.com/thread-130295-1-1.html(这篇对DLX的工作过程演示的很详细) http://yzmduncan.iteye.co ...

  2. 【转】Dancing Links精确覆盖问题

    原文链接:http://sqybi.com/works/dlxcn/ (只转载过来一部分,全文请看原文,感觉讲得很好~)正文    精确覆盖问题    解决精确覆盖问题    舞蹈步骤    效率分析 ...

  3. hihoCoder #1321 : 搜索五•数独 (Dancing Links ,精确覆盖)

    hiho一下第102周的题目. 原题地址:http://hihocoder.com/problemset/problem/1321 题意:输入一个9*9数独矩阵,0表示没填的空位,输出这个数独的答案. ...

  4. hust 1017 dancing links 精确覆盖模板题

    最基础的dancing links的精确覆盖题目 #include <iostream> #include <cstring> #include <cstdio> ...

  5. ZOJ 3209 Treasure Map (Dancing Links 精确覆盖 )

    题意 :  给你一个大小为 n * m 的矩形 , 坐标是( 0 , 0 ) ~ ( n , m )  .然后给你 p 个小矩形 . 坐标是( x1 , y1 ) ~ ( x2 , y2 ) , 你选 ...

  6. HUST1017 Exact cover —— Dancing Links 精确覆盖 模板题

    题目链接:https://vjudge.net/problem/HUST-1017 1017 - Exact cover 时间限制:15秒 内存限制:128兆 自定评测 7673 次提交 3898 次 ...

  7. HDU5046 Airport dancing links 重复覆盖+二分

    这一道题和HDU2295是一样 是一个dancing links重复覆盖解决最小支配集的问题 在给定长度下求一个最小支配集,只要小于k就行 然后就是二分答案,每次求最小支配集 只不过HDU2295是浮 ...

  8. hdu 1426 Sudoku Killer ( Dancing Link 精确覆盖 )

    利用 Dancing Link 来解数独 详细的能够看    lrj 的训练指南 和 < Dancing Links 在搜索中的应用 >这篇论文 Dancing Link 来求解数独 , ...

  9. poj 3074 Sudoku(Dancing Links)

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

随机推荐

  1. WebView跳转到底部

    webview中有个computeVerticalScrollRange方法,是protected的,可以用反射,也可以自己写一个view继承webview,实现computeVerticalScro ...

  2. Oracle外键级联删除和级联更新

    https://www.2cto.com/database/201507/417496.html

  3. python练习之-计算器

    学习以堆栈模式编写-计算器 堆栈特点:先进后出, 如下: #!/opt/python3/bin/python3 # Author: yong import re def is_symbol(eleme ...

  4. CodeForces - 813C The Tag Game (树的dfs遍历)

    [传送门]http://codeforces.com/problemset/problem/813/C [题目大意]两个人玩游戏,一个人跑一个人追,轮流决策,可以走也可以不走.给你一棵树,想要从某个结 ...

  5. DFS与BFS对比

    前面已经说过了深搜和广搜了,是不是有点还不是很好的分清他们?(其实分不分的请都没大有关系) 下面我们来看一看广搜与深搜的区别吧. 算法步骤上的区别 深度优先遍历图算法步骤: 1.访问顶点v 2,.依次 ...

  6. java.nio.ByteBuffer 以及flip,clear及rewind区别

    Buffer 类 定义了一个可以线性存放primitive type数据的容器接口.Buffer主要包含了与类型(byte, char…)无关的功能. 值得注意的是Buffer及其子类都不是线程安全的 ...

  7. 利用广播调用后台服务方法并根据方法返回的内容更新UI

    一.UI布局代码 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns ...

  8. 使用webstorm+webpack构建简单入门级“HelloWorld”的应用&&构建使用jquery来实现

    使用webstorm+webpack构建简单入门级“HelloWorld”的应用&&构建使用jquery来实现 1.首先你自己把webstorm安装完成. 请参考这篇文章进行安装和破解 ...

  9. Linux多线程实例 定时重启httpd和mysqld

    #include <stdio.h> #include <pthread.h> void *start_routine(void *arg) { while(1) { syst ...

  10. 线性表的顺序存储和链式存储的实现(C)

    //线性表的顺序存储 #include <stdio.h>typedef int DataType;#define MaxSize 15//定义顺序表typedef struct { Da ...