#include <stdio.h> #include <string.h> using namespace std; struct DLX { const static int maxn=750,maxm=350,maxnode=maxn*maxm; int n,m,sz,anssz; int u[maxnode],d[maxnode],l[maxnode],r[maxnode],row[maxnode],col[maxnode]; //row col 记录该节点i坐标 int h[maxn],colcnt[maxm]; //排头及列节点计数 int ans[maxn]; void init(int _n,int _m) //数据位于1,1...n,m { n=_n,m=_m; for(int i=0;i<=m;i++)//1..m是每一列的辅助结点 0代表(0,0)即head { u[i]=d[i]=i; l[i]=i-1;r[i]=i+1; col[i]=i;row[i]=0; colcnt[i]=0; } l[0]=m;r[m]=0; sz=m;anssz=0; for(int i=1;i<=n;i++)h[i]=-1; } inline void push(int x,int y) { colcnt[y]++; col[++sz]=y; row[sz]=x; d[sz]=d[y]; //加入列首元素后面 u[sz]=y; u[d[y]]=sz; d[y]=sz; if(h[x]<0) h[x]=r[sz]=l[sz]=sz; //成为行首元素 else{ int hd=h[x]; //加入行首节点右边 l[sz]=hd; r[sz]=r[hd]; l[r[hd]]=sz; r[hd]=sz; } } inline void exact_remove(int x) //列首节点 { r[l[x]]=r[x];//left's right=right l[r[x]]=l[x];//right's left=left //左右节点跳过列首节点,自己的信息依然保留 for(int i=d[x];i!=x;i=d[i]) //删除该列占据的每一行除该列的元素的上下连接 for(int j=r[i];j!=i;j=r[j])//,节点信息本身依然保留 d[u[j]]=d[j],u[d[j]]=u[j],colcnt[col[j]]--; } inline void exact_resume(int x)//恢复del操作 { for(int i=u[x];i!=x;i=u[i]) //注意逆操作的顺序 for(int j=l[i];j!=i;j=l[j]) colcnt[col[ d[u[j]] = u[d[j]] = j]]++; r[l[x]]=l[r[x]]=x; } bool dance(int dep) { if(r[0]==0) { anssz=dep; return true; } int cur=r[0]; for(int i=r[0];i!=0;i=r[i])if(colcnt[i]<colcnt[cur])cur=i; exact_remove(cur); for(int i=d[cur];i!=cur;i=d[i]) { ans[dep]=row[i]; for(int j=r[i];j!=i;j=r[j]) exact_remove(col[j]); if(dance(dep+1)) return true; for(int j=l[i];j!=i;j=l[j]) exact_resume(col[j]); //注意逆操作的顺序 } exact_resume(cur); return false; } void preprocess() { for(int i=r[0];i;i=r[i]) if(colcnt[i]==0) { l[r[i]]=l[i],r[l[i]]=r[i]; } } }; DLX dlx; inline int encode(int a,int b,int c) { return a*81+b*9+c+1; } inline int decode(int a,int &b,int& c,int &d) { a--; b=a/81; d=a%9; c=a/9%9; } const int n=9; int main() { #ifdef shuaishuai freopen("in.txt","r",stdin); #endif // shuaishuai static char s[100]; while(~scanf("%s",s)&&s[0]!='e') { dlx.init(encode(8,8,9),encode(3,9,9)); for(int i=0;i<n;i++) for(int j=0;j<n;j++) { char c=s[i*n+j]; for(int k=0;k<n;k++) if(c=='.'||c==k+'1'){ int category=encode(i,j,k); dlx.push(category,encode(0,i,j)); //mp[i][j] dlx.push(category,encode(1,i,k)); //row k dlx.push(category,encode(2,j,k)); //col k dlx.push(category,encode(3,i/3*3+j/3,k)); // } } dlx.preprocess(); dlx.dance(0); for(int i=0,sz=dlx.anssz,*a=dlx.ans,x,y,z;i<sz;i++) { decode(a[i],x,y,z); s[x*n+y]='1'+z; } puts(s); } // printf("%d\n",9*9*9+9*9+9); return 0; }
POJ 3074 Sudoku 精确覆盖构造
猜你喜欢
转载自www.cnblogs.com/polya/p/9770337.html
今日推荐
周排行