Sudoku
Time Limit: 10000MS | Memory Limit: 65536K | |
Total Submissions: 4918 | Accepted: 2332 |
Description
A Sudoku grid is a 16x16 grid of cells grouped in sixteen 4x4 squares, where some cells are filled with letters from A to P (the first 16 capital letters of the English alphabet), as shown in figure 1a. The game is to fill all the empty grid cells with letters from A to P such that each letter from the grid occurs once only in the line, the column, and the 4x4 square it occupies. The initial content of the grid satisfies the constraints mentioned above and guarantees a unique solution.
Write a Sudoku playing program that reads data sets from a text file.
![](https://i-blog.csdnimg.cn/blog_migrate/90086514c2c223ed0ea43404546b4a09.jpeg)
Write a Sudoku playing program that reads data sets from a text file.
Input
Each data set encodes a grid and contains 16 strings on 16 consecutive lines as shown in figure 2. The i-th string stands for the i-th line of the grid, is 16 characters long, and starts from the first position of the line. String characters are from the set {A,B,…,P,-}, where – (minus) designates empty grid cells. The data sets are separated by single empty lines and terminate with an end of file.
Output
The program prints the solution of the input encoded grids in the same format and order as used for input.
Sample Input
--A----C-----O-I -J--A-B-P-CGF-H- --D--F-I-E----P- -G-EL-H----M-J-- ----E----C--G--- -I--K-GA-B---E-J D-GP--J-F----A-- -E---C-B--DP--O- E--F-M--D--L-K-A -C--------O-I-L- H-P-C--F-A--B--- ---G-OD---J----H K---J----H-A-P-L --B--P--E--K--A- -H--B--K--FI-C-- --F---C--D--H-N-
Sample Output
FPAHMJECNLBDKOGI OJMIANBDPKCGFLHE LNDKGFOIJEAHMBPC BGCELKHPOFIMAJDN MFHBELPOACKJGNID CILNKDGAHBMOPEFJ DOGPIHJMFNLECAKB JEKAFCNBGIDPLHOM EBOFPMIJDGHLNKCA NCJDHBAEKMOFIGLP HMPLCGKFIAENBDJO AKIGNODLBPJCEFMH KDEMJIFNCHGAOPBL GLBCDPMHEONKJIAF PHNOBALKMJFIDCEG IAFJOECGLDPBHMNK
Source
数独题目
只不过变成了16x16的数独……
正好也整理下数独模板
题目中给的数据好像是pdf直接拷贝出bug的缘故
poj的是正常的LA和ZOJ好像都有问题
基本点不变
如果数独是M*M的
那么有M*M*M行
对应i行j列填数字k
M*M*4列
1~M*M i行j列有数字
M*M+1~M*M*2 i行有数字j
M*M*2+1~M*M*3 i列有数字j
M*M*3+1~M*M*4 i小九宫有数字j
特别测试
列的排布会大范围的影响速度
同样的程序如果交换“i行j列有数字”列与“i小九宫有数字j”列
效率会低10倍……
使用place函数可以方便的算出第几个小九宫
而且place变成类的成员函数速度更快(应该是被inline了,直接inline应该也可以……)
#include <iostream>
#include <stdio.h>
#include <string.h>
using namespace std;
const int M=16;//数独大小
const int MN=M*M*M+10;
const int MM=M*M*4+10;
const int MNN=MN*4+MM; //最大点数,数独问题节点没有那么多
struct DLX
{
int n,m,si;//n行数m列数si目前有的节点数
//十字链表组成部分
int U[MNN],D[MNN],L[MNN],R[MNN],Row[MNN],Col[MNN];
//第i个结点的U向上指针D下L左R右,所在位置Row行Col列
int H[MN],S[MM]; //记录行的选择情况和列的覆盖情况
int ansd,ans[MN];
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;
si=m; //目前用了前0~m个结点
for(int i=1;i<=n;i++)
H[i]=-1;
}
void link(int r,int c) //插入点(r,c)
{
//cout<<"link r "<<r<<" c "<<c<<endl;
++S[Col[++si]=c]; //si++;Col[si]=c;S[c]++;
Row[si]=r;
D[si]=D[c];
U[D[c]]=si;
U[si]=c;
D[c]=si;
if(H[r]<0)
H[r]=L[si]=R[si]=si;
else
{
R[si]=R[H[r]];
L[R[H[r]]]=si;
L[si]=H[r];
R[H[r]]=si;
}
}
void remove(int c) //列表中删掉c列
{
//cout<<"remove "<<c<<endl;
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) //恢复c列
{
//cout<<"resume "<<c<<endl;
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;
}
bool dance(int d) //选取了d行
{
if(R[0]==0)//全部覆盖了
{
//全覆盖了之后的操作
ansd=d;
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 1;
for(int j=L[i];j!=i;j=L[j])
resume(Col[j]);
}
resume(c);
return 0;
}
void place(int &r,int &c1,int &c2,int &c3,int &c4,int i,int j,int k)
{
r=(i*M+j)*M+k;
c1=M*M*0+i*M+j+1;
c2=M*M*1+i*M+k;
c3=M*M*3+j*M+k;
c4=M*M*2+((i/4)*4+(j/4))*M+k;//确定第几个小九宫(16宫?),九宫4改3
}
}dlx;
char ss[M+5][M+5];
int main()
{
//freopen("1.in","r",stdin);
//freopen("1.out","w",stdout);
int ca=0;
while(scanf("%s",ss[0])!=EOF)
{
for(int i=1;i<M;i++)
scanf("%s",ss[i]);
dlx.init(M*M*M,M*M*4);
int r,c1,c2,c3,c4;
for(int i = 0;i < M;i++)
for(int j = 0;j < M;j++)
for(int k = 1;k <= M;k++)
if(ss[i][j] == '-' || ss[i][j] == 'A'+k-1)
{
dlx.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);
int v,x,y;
for(int i=0;i<dlx.ansd;i++)
{
v=(dlx.ans[i]-1)%M;
x=(dlx.ans[i]-1)/M/M;
y=(dlx.ans[i]-1)/M%M;
ss[x][y]=v+'A';
}
if(ca++)
printf("\n");
for(int i=0;i<M;i++)
printf("%s\n",ss[i]);
}
return 0;
}