Poj3074-Sudoku(数独DLX)
题意: 给出一个9*9的矩阵,有一些格子已经填了数,有一些是.代表未填。求任意一组解使得每行包含1~9,每列包含1~9,每个小矩形(3*3)包含1~9。
解析: 精确覆盖DLX的经典题目,每一行代表要填数的情况,列共有81*4行,第一个81行代表第i行j列放了数,第二个81列代表第i行放的数k,第三个81列
代表第j列放的数k,第四个81行代表第i个小矩形放的数k。对于字符为.的情况添加9行,对于字符为数字的情况添加一行。然后就是跑一遍DLX,保存一下答案
输出即可。
代码
#include<cstdio> #include<cstring> #include<string> #include<algorithm> using namespace std; const int INF=1e9+7; const int ms=81*10; const int maxn=ms*4; int ans[maxn]; struct DLX { int n,id; int L[maxn],R[maxn],U[maxn],D[maxn]; int C[maxn],S[maxn],loc[maxn][3]; int H[ms]; void init(int nn=0) { n=nn; for(int i=0;i<=n;i++) U[i]=D[i]=i,L[i]=i-1,R[i]=i+1; L[0]=n; R[n]=0; id=n; memset(S,0,sizeof(S)); memset(H,-1,sizeof(H)); } void Link(int x,int y,int px,int py,int k) { ++id; D[id]=y; U[id]=U[y]; D[U[y]]=id; U[y]=id; loc[id][0]=px,loc[id][1]=py,loc[id][2]=k; C[id]=y; S[y]++; if(H[x]==-1) H[x]=L[id]=R[id]=id; else { int a=H[x]; int b=R[a]; L[id]=a; R[a]=id; R[id]=b; L[b]=id; H[x]=id; } } 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[C[j]]--; } } void Resume(int c) { for(int i=U[c];i!=c;i=U[i]) for(int j=R[i];j!=i;j=R[j]) { S[C[j]]++; U[D[j]]=j; D[U[j]]=j; } L[R[c]]=c; R[L[c]]=c; } bool dfs(int step) { if(step==81) return true; if(R[0]==0) return false; int Min=INF,c=-1; for(int i=R[0];i;i=R[i]) if(Min>S[i]){ Min=S[i]; c=i; } Remove(c); for(int i=D[c];i!=c;i=D[i]) { ans[step]=i; for(int j=R[i];j!=i;j=R[j]) Remove(C[j]); if(dfs(step+1)) return true; for(int j=L[i];j!=i;j=L[j]) Resume(C[j]); } Resume(c); return false; } }dlx; int main() { char S[90]; while(scanf("%s",S)!=EOF) { if(S[0]=='e') break; dlx.init(81*4); int k=0,r=0; for(int x=0;x<9;x++) for(int y=0;y<9;y++) { char ch=S[k++]; int a,b,c,d; if(ch=='.') { for(int i=1;i<=9;i++) { a=x*9+y+1; b=x*9+i+81; c=y*9+i+81+81; int s=(x/3)*3+y/3; d=s*9+i+81+81+81; ++r; dlx.Link(r,a,x,y,i); dlx.Link(r,b,x,y,i); dlx.Link(r,c,x,y,i); dlx.Link(r,d,x,y,i); } } else { int i=ch-'0'; a=x*9+y+1; b=x*9+i+81; c=y*9+i+81+81; int s=(x/3)*3+y/3; d=s*9+i+81+81+81; ++r; dlx.Link(r,a,x,y,i); dlx.Link(r,b,x,y,i); dlx.Link(r,c,x,y,i); dlx.Link(r,d,x,y,i); } } dlx.dfs(0); int res[10][10]; for(int i=0;i<81;i++) { int a=ans[i]; int x=dlx.loc[a][0],y=dlx.loc[a][1],k=dlx.loc[a][2]; res[x][y]=k; } for(int i=0;i<9;i++) for(int j=0;j<9;j++) printf("%d",res[i][j]); printf("\n"); } return 0; }