题目大意:。。。。数独还用我说么
首先一般的解法都是爆搜,爆搜的话绝对懒得做。。于是我作死去学了Dancing-Links数据结构优化的X算法,简称DLX算法
Dancing-Links虽然名字好听,但是其实实质就是双向十字链表。。但是由于调试的时候各种挂,指针还看着及其闹心(经常调试链式结构的人一定深有同感),所以只能在调试区各种加指针删指针,来回飞舞的指针,即Dancing-Links。。。
这算法的作者太有才了,不得不说。。。。
DLX算法主要解决的是精确覆盖问题,具体做法见 http://www.cnblogs.com/grenet/p/3145800.html
这里我们要把数独问题转化为精确覆盖问题
首先数独的约束条件是什么?
1.一个格子里只能放一个数
2.每行同一数字只能放一个
3.每列同一数字只能放一个
4.每个九宫格中同一数字只能放一个
于是我们每一行就有四组约束条件:
1.81列,代表这个格子中已经放了数字
2.81列,代表第i行已经放了数字j
3.81列,代表第i列已经放了数字j
4.81列,代表第i个九宫格中已经放了数字j
然后每个格子的每种填放可能作为一行加进去就可以了
记住一定要采用A*算法,不然会死!
每次选择当前拥有1最少的列进行更新,不然必死无疑
最后贴代码 我的head开在了十字链表的最下方 加行比较方便
<pre class="sh_cpp sh_sourceCode" style="background-color: white;font-size:14px; font-family: 'Courier New', Courier, monospace;"><pre name="code" class="html">#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std; struct abcd *stack[4000]; int top; struct abcd{ abcd *l,*r,*u,*d; int x,y,num; abcd *bottom; abcd(abcd *L,abcd *R,abcd *U,abcd *D,int X,int Y,int Num) { l=L;if(L)L->r=this; r=R;if(R)R->l=this; u=U;if(U)U->d=this; d=D;if(D)D->u=this; x=X;y=Y;num=Num; bottom=d; if(bottom) bottom->x++; } void del() { if(l)l->r=r; if(r)r->l=l; if(u)u->d=d; if(d)d->u=u; if(bottom) bottom->x--; stack[++top]=this; } void restore() { if(l)l->r=this; if(r)r->l=this; if(u)u->d=this; if(d)d->u=this; if(bottom) bottom->x++; } }*head,*heads[400]; int m,n,map[9][9]; bool flag; void del_column(int pos) { abcd *temp1,*temp2; for(temp1=heads[pos]->u;temp1;temp1=temp1->u) { for(temp2=temp1->l;temp2;temp2=temp2->l) temp2->del(); for(temp2=temp1->r;temp2;temp2=temp2->r) temp2->del(); temp1->del(); } heads[pos]->del(); } inline void output() { int i,j; for(i=0;i<9;i++) { for(j=0;j<9;j++) putchar(map[i][j]+'0'); putchar('\n'); } } void DLX() { if(!head->r) { output(); flag=1; return ; } int bottom=top,minnum=0x7fffffff; abcd *temp,*mintemp; for(temp=head->r;temp;temp=temp->r) if(temp->x<minnum) minnum=temp->x,mintemp=temp; for(temp=mintemp->u;temp;temp=temp->u) { int x=temp->x,y=temp->y,num=temp->num; map[x][y]=num; del_column(x*9+y+1 ); del_column(81+x*9+num ); del_column(162+y*9+num ); del_column(243+(x/3*3+y/3)*9+num ); DLX(); if(flag) return ; while(top!=bottom) stack[top--]->restore(); } } void add(int x,int y,int num) { abcd *last=0x0,*temp; temp=heads[x*9+y+1 ],last=new abcd(last,0x0,temp->u,temp,x,y,num); temp=heads[81+x*9+num ],last=new abcd(last,0x0,temp->u,temp,x,y,num); temp=heads[162+y*9+num ],last=new abcd(last,0x0,temp->u,temp,x,y,num); temp=heads[243+(x/3*3+y/3)*9+num ],last=new abcd(last,0x0,temp->u,temp,x,y,num); } int main() { int T,i,j,k,x; abcd *temp,*last; //freopen("sudoku.in","r",stdin); //freopen("sudoku.out","w",stdout); for(cin>>T;T;T--) { head=new abcd(0x0,0x0,0x0,0x0,0,0,0);top=0;flag=0; for(i=1,last=head;i<=81*4;i++) last=new abcd(last,0x0,0x0,0x0,0,0,i),heads[i]=last; for(i=0;i<9;i++) for(j=0;j<9;j++) scanf("%1d",&map[i][j]); for(i=0;i<9;i++) for(j=0;j<9;j++) if(map[i][j]) add(i,j,map[i][j]); else for(k=1;k<=9;k++) add(i,j,k); DLX(); } }