Language:
Sudoku
Description In the game of Sudoku, you are given a large 9 × 9 grid divided into smaller 3 × 3 subgrids. For example,
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 |
裸的求数独可行解的题
数独问题
采用跳舞链方法会得到比较快的速度
用跳舞链解决的方法主要是将问题的模型转换成01覆盖模型,然后模板之
首先要了解它的限制条件:
(1) 每一格只能填一个数字
(2) 每一列的数字是不同的
(3) 每一行的数字是不同的
(4) 每一个九宫格的数字是不同的
那么我们可以构造出一组状态:
行状态(i,j,k):表示第i行第j列填第k个数
列状态(i,j,k):表示第k个限制的子状态为(i,j),子状态根据限制而定
所以对于N层数独来说,行有N*N*N,列有4*N*N
然后对于给出的数独,如果改格子没有数字就枚举每个可能出现的数字插入,有数字就插入现成的,然后用跳舞链一下,就出结果了
#include <cstdio>
#include <iostream>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <string.h>
#include <string>
#include <vector>
#include <queue>
#define MEM(a,x) memset(a,x,sizeof a)
#define eps 1e-8
#define MOD 10009
#define INF 99999999
#define ll __int64
#define bug cout<<"here"<<endl
#define fread freopen("ceshi.txt","r",stdin)
#define fwrite freopen("out.txt","w",stdout)
using namespace std;
const int N=9;
const int MAXN=N*N*N+10;
const int MAXM=N*N*4+10;
const int maxnode=MAXN*4+MAXM+10;
char ch[MAXN];
struct DLX
{
int n,m,size;
int U[maxnode],D[maxnode],R[maxnode],L[maxnode],Row[maxnode],Col[maxnode];
int H[MAXN], S[MAXM];
int ansd, ans[MAXN];
void init(int _n,int _m)
{
n = _n;
m = _m;
for(int i = 0;i <= m;i++)
{
S[i] = 0;
U[i] = D[i] = i;
L[i] = i-1;
R[i] = i+1;
}
R[m] = 0; L[0] = m;
size = m;
for(int i = 1;i <= n;i++)
H[i] = -1;
}
void Link(int r,int c)
{
++S[Col[++size]=c];
Row[size] = r;
D[size] = D[c];
U[D[c]] = size;
U[size] = c;
D[c] = size;
if(H[r] < 0)H[r] = L[size] = R[size] = size;
else
{
R[size] = R[H[r]];
L[R[H[r]]] = size;
L[size] = H[r];
R[H[r]] = size;
}
}
void remove(int c)
{
L[R[c]] = L[c]; R[L[c]] = R[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)
{
for(int i = U[c];i != c;i = U[i])
for(int j = L[i];j != i;j = L[j])
++S[Col[U[D[j]]=D[U[j]]=j]];
L[R[c]] = R[L[c]] = c;
}
//d为递归深度
bool Dance(int d)
{
if(R[0] == 0)
{
for(int i=0;i<d;i++) ch[(ans[i]-1)/9]=(ans[i]-1)%9+'1';
for(int i=0;i<N*N;i++) printf("%c",ch[i]);
puts("");
return 1;
}
int c = R[0];
for(int i = R[0];i != 0;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+1))return true;
for(int j = L[i]; j != i;j = L[j])resume(Col[j]);
}
resume(c);
return false;
}
}dlx;
void place(int &r,int &c1,int &c2,int &c3,int &c4,int i,int j,int k)
{
r=(i*N+j)*N+k; c1=i*N+j+1; c2=N*N+i*N+k;
c3=N*N*2+j*N+k; c4=N*N*3+((i/3)*3+(j/3))*N+k;
}
int main()
{
// fread;
while(scanf("%s",ch)!=EOF)
{
if(strcmp(ch,"end")==0) break;
dlx.init(N*N*N,N*N*4);
int r,c1,c2,c3,c4;
for(int i=0;i<N;i++)
for(int j=0;j<N;j++)
for(int k=1;k<=N;k++)
if(ch[i*N+j]=='.'||ch[i*N+j]=='0'+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(0);
}
return 0;
}