​题目​​(传送门)题意概括

给出一个残缺的数独,求解。SPJ

 

题解

DLX  +  矩阵构建  (两个传送门)

 

代码



#include <cstring>
#include <cstdio>
#include <algorithm>
#include <cstdlib>
#include <cmath>
using namespace std;
const int N=800,M=400,S=N*4+M;
struct DLX{
int n,m,cnt;
int x[S],y[S],L[S],R[S],U[S],D[S];
int C[M],anscnt,ans[N];
void init(int c){
memset(x,0,sizeof x);
memset(y,0,sizeof y);
memset(L,0,sizeof L);
memset(R,0,sizeof R);
memset(U,0,sizeof U);
memset(D,0,sizeof D);
memset(C,0,sizeof C);
memset(ans,0,sizeof ans);
anscnt=0;
m=c;
for (int i=0;i<=m;i++)
L[i]=i-1,R[i]=i+1,U[i]=D[i]=i;
L[0]=m,R[m]=0,cnt=m;
}
void link(int i,int j){
cnt++;
x[cnt]=i;
y[cnt]=j;
L[cnt]=cnt-1;
R[cnt]=cnt+1;
D[cnt]=j;
D[U[j]]=cnt;
U[cnt]=U[j];
U[j]=cnt;
C[j]++;
}
void Delete(int k){
L[R[k]]=L[k];
R[L[k]]=R[k];
for (int i=D[k];i!=k;i=D[i])
for (int j=R[i];j!=i;j=R[j]){
U[D[j]]=U[j];
D[U[j]]=D[j];
C[y[j]]--;
}
}
void Reset(int k){
L[R[k]]=k;
R[L[k]]=k;
for (int i=U[k];i!=k;i=U[i])
for (int j=L[i];j!=i;j=L[j]){
U[D[j]]=j;
D[U[j]]=j;
C[y[j]]++;
}
}
bool solve(){
if (R[0]==0)
return true;
anscnt++;
int k=R[0];
for (int i=R[k];i!=0;i=R[i])
if (C[i]<C[k])
k=i;
Delete(k);
for (int i=D[k];i!=k;i=D[i]){
ans[anscnt]=x[i];
for (int j=R[i];j!=i;j=R[j])
Delete(y[j]);
if (solve())
return true;
for (int j=L[i];j!=i;j=L[j])
Reset(y[j]);
}
Reset(k);
anscnt--;
return false;
}
}dlx;
int T,a[15][15],x[800],y[800],z[800];
char s[15];
int hash(int a,int b,int c){
return a*81+b*9+c+1;
}
int main(){
scanf("%d",&T);
while (T--){
for (int i=1;i<=9;i++){
scanf("%s",s+1);
for (int j=1;j<=9;j++)
a[i][j]=s[j]-48;
}
dlx.init(9*9*4);
int Row=0;
for (int i=1;i<=9;i++)
for (int j=1;j<=9;j++){
int st,en;
if (a[i][j]==0)
st=1,en=9;
else
st=en=a[i][j];
for (int k=st;k<=en;k++){
Row++;
x[Row]=i,y[Row]=j,z[Row]=k;
int first=dlx.cnt+1;
dlx.link(Row,hash(0,i-1,j-1));
dlx.link(Row,hash(1,i-1,k-1));
dlx.link(Row,hash(2,j-1,k-1));
dlx.link(Row,hash(3,((i-1)/3)*3+(j-1)/3,k-1));
dlx.L[first]=dlx.cnt;
dlx.R[dlx.cnt]=first;
}
}
bool found=dlx.solve();
for (int i=1;i<=dlx.anscnt;i++)
a[x[dlx.ans[i]]][y[dlx.ans[i]]]=z[dlx.ans[i]];
for (int i=1;i<=9;puts(""),i++)
for (int j=1;j<=9;j++)
printf("%d",a[i][j]);
}
return 0;
}