16*16的数独题。网上已经有很多解释了,关于解法推荐博客:https://blog.csdn.net/bl0ss0m/article/details/17918705
这里用来保存舞蹈链模板!
#include <stdio.h> using namespace std; typedef long long ll; const int MAXN = 16*16*16+10; const int MAXM = 16*16*4+10; const int MAXNODE=MAXN*MAXM+MAXM; const int INF = 0x3f3f3f3f; char s[20][20]; //精确匹配模板 struct DLX{ int N,M,size; int U[MAXNODE],D[MAXNODE],R[MAXNODE],L[MAXNODE]; int Row[MAXNODE],Col[MAXNODE]; int H[MAXN],S[MAXM]; int ansd;//答案用了多少行 int ansh[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; } bool dance(int d){ //if(ansd<d) // return; 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]){ ansh[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 false; } }; DLX g; //重复匹配模板 struct DLX_C{ int N,M,size; int U[MAXNODE],D[MAXNODE],R[MAXNODE],L[MAXNODE]; int Row[MAXNODE],Col[MAXNODE]; int H[MAXN],S[MAXM]; int K; 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){ for(int i=D[c];i!=c;i=D[i]) L[R[i]]=L[i],R[L[i]]=R[i]; } void resume(int c){ for(int i=U[c];i!=c;i=U[i]) L[R[i]]=R[L[i]]=i; } bool v[MAXNODE]; int f() { int ret = 0; for(int c = R[0];c != 0;c = R[c])v[c] = true; for(int c = R[0];c != 0;c = R[c]) if(v[c]) { ret++; v[c] = false; for(int i = D[c];i != c;i = D[i]) for(int j = R[i];j != i;j = R[j]) v[Col[j]] = false; } return ret; } bool dance(int d) { if(d + f() > K)return false; if(R[0] == 0)return d <= K; int c = R[0]; for(int i = R[0];i != 0;i = R[i]) if(S[i] < S[c]) c = i; for(int i = D[c];i != c;i = D[i]) { remove(i); for(int j = R[i];j != i;j = R[j])remove(j); if(dance(d+1))return true; for(int j = L[i];j != i;j = L[j])resume(j); resume(i); } return false; } }; //DLX_C g; //用与数独快速求解填了是哪一个数字 int encode(int a,int b,int c) { return a*256+b*16+c+1; } void decode(int code,int &a,int &b,int &c) { code--; c=code%16;code/=16; b=code%16;code/=16; a=code; } int main(){ bool first=true; while(scanf("%s",s[0])!=EOF) { if(first)first=false; else printf("\n"); for(int i=1;i<16;i++) scanf("%s",s[i]); g.init(16*16*16,16*16*4); for(int r=0;r<16;r++) for(int c=0;c<16;c++) for(int v=0;v<16;v++) if(s[r][c]=='-'||s[r][c]=='A'+v) { int row=encode(r,c,v); g.Link(row,encode(0,r,c)); g.Link(row,encode(1,r,v)); g.Link(row,encode(2,c,v)); g.Link(row,encode(3,(r/4)*4+c/4,v)); } g.dance(0); for(int i=0;i<g.ansd;i++) { int r,c,v; decode(g.ansh[i],r,c,v); s[r][c]='A'+v; } for(int i=0;i<16;i++) printf("%s\n",s[i]); } return 0; }