题目大意:。。。。数独还用我说么
首先一般的解法都是爆搜,爆搜的话绝对懒得做。。于是我作死去学了Dancing-Links数据结构优化的X算法,简称DLX算法
Dancing-Links虽然名字好听,但是其实实质就是双向十字链表。。但是由于调试的时候各种挂,指针还看着及其闹心(经常调试链式结构的人一定深有同感),所以只能在调试区各种加指针删指针,来回飞舞的指针,即Dancing-Links。。。
这算法的作者太有才了,不得不说。。。。
DLX算法主要解决的是精确覆盖问题
这里我们要把数独问题转化为精确覆盖问题
首先数独的约束条件是什么?
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();
}
}