POJ3076 Sudoku 舞蹈链 DLX
欢迎访问~原文出处——博客园-zhouzhendong
去博客园看该题解
题目(传送门)
题意概括
给出一个残缺的16*16数独,求解。
题解
学完这个之后,再思考这一题。同样,每个位置每种取值4个信息。
数独共256个格子,每个格子都得填一个数,那么,我们要精确覆盖每一个格子,所以我们首先建立1~256列。
然后还有16行,每行1~16,每行都得精确覆盖,16行,又得建立16*16=256列;
然后还有16列,每列1~16,同理。
然后还有16个4*4的小格子,每个里面1~16,也同理。
那么总共要建立4*256=1024列。
代码
#include <cstring> #include <cstdio> #include <algorithm> #include <cstdlib> #include <cmath> using namespace std; const int N=4100,M=1050,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 a[20][20],x[N],y[N],z[N]; char s[20]; int hash(int a,int b,int c){ return a*256+b*16+c+1; } int main(){ while (~scanf("%s",s+1)){ for (int i=1;i<=16;i++){ for (int j=1;j<=16;j++) if (s[j]=='-') a[i][j]=0; else a[i][j]=s[j]-'A'+1; if (i<16) scanf("%s",s+1); } dlx.init(1024); int Row=0; for (int i=1;i<=16;i++) for (int j=1;j<=16;j++){ int st,en; if (a[i][j]==0) st=1,en=16; 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)/4)*4+(j-1)/4,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<=16;puts(""),i++) for (int j=1;j<=16;j++) printf("%c",a[i][j]+'A'-1); puts(""); } return 0; }