版权声明:作为一个蒟蒻,转载时请通知我这个蒟蒻 https://blog.csdn.net/zyszlb2003/article/details/89412503
数独问题转化为精确覆盖问题基本思路
详情参考:算法实践——舞蹈链(Dancing Links)算法求解数独 - 万仓一黍 - 博客园
POJ2676
代码
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<cstdlib>
#include<bitset>
using namespace std;
const int N=3310;
const int M=331;
const int g[9][9]=
{
{0,0,0,1,1,1,2,2,2,},
{0,0,0,1,1,1,2,2,2,},
{0,0,0,1,1,1,2,2,2,},
{3,3,3,4,4,4,5,5,5,},
{3,3,3,4,4,4,5,5,5,},
{3,3,3,4,4,4,5,5,5,},
{6,6,6,7,7,7,8,8,8,},
{6,6,6,7,7,7,8,8,8,},
{6,6,6,7,7,7,8,8,8,},
};
int num,r[N],l[N],d[N],u[N],col[N],sz[M],head;
int a[10][10];
void remove(int p)
{
l[r[p]]=l[p],r[l[p]]=r[p];
for(int i=u[p];i!=p;i=u[i])
for(int j=r[i];j!=i;j=r[j])
u[d[j]]=u[j],d[u[j]]=d[j];
}
void resume(int p)
{
l[r[p]]=r[l[p]]=p;
for(int i=u[p];i!=p;i=u[i])
for(int j=r[i];j!=i;j=r[j])
u[d[j]]=d[u[j]]=j;
}
void link(int j)
{
++num;
u[num]=u[j];d[num]=j;col[num]=j;
u[d[num]]=d[u[num]]=num;++sz[j];
if(!head)head=num;
else l[num]=num-1,r[num-1]=num;
}
void make(int i,int j,int k)//i行,j列,填k
{
head=0;
link(i*9+j+1),link(81+i*9+k),link(162+j*9+k),link(243+g[i][j]*9+k);
l[head]=num;r[num]=head;
}
bool bk;
void dance()
{
if(!r[0])
{
for(int i=1;i<=9;i++)
{
for(int j=1;j<=9;j++)
{
printf("%d",a[i][j]);
}
puts("");
}
bk=true;return ;
}
int p=r[0],x,y;
for(int i=r[p];i;i=r[i])if(sz[i]<sz[p])p=i;
remove(p);
for(int i=d[p];i!=p;i=d[i])
{
if(0<col[i]&&col[i]<=81)x=col[i];
else if(81<col[i]&&col[i]<=162)y=col[i];
for(int j=r[i];j!=i;j=r[j])
{
remove(col[j]);
if(0<col[j]&&col[j]<=81)x=col[j];
else if(81<col[j]&&col[j]<=162)y=col[j];
}
a[(x-1)/9+1][(x-1)%9+1]=(y-1)%9+1;dance();if(bk)return ;
for(int j=r[i];j!=i;j=r[j])resume(col[j]);
}
resume(p);
}
char s[10];
int main()
{
int t;scanf("%d",&t);
while(t--)
{
num=324;bk=false;//memset(r,0,sizeof(r));memset(l,0,sizeof(l)),memset(u,0,sizeof(u));
//memset(d,0,sizeof(d));head=0;memset(sz,0,sizeof(sz));memset(col,0,sizeof(col));
memset(sz,0,sizeof(sz));head=0;
for(int i=0;i<=num;i++)l[i]=i-1,r[i]=i+1,u[i]=d[i]=i;
l[0]=num;r[num]=0;
for(int i=0;i<9;i++)
{
scanf("%s",s);
for(int j=0;j<9;j++)
{
int x=s[j]-'0';
if(x)make(i,j,x);
else for(int k=1;k<=9;k++)make(i,j,k);
}
}
dance();
}
return 0;
}
POJ3074
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<cstdlib>
#include<bitset>
using namespace std;
const int N=3310;
const int M=331;
const int g[9][9]=
{
{0,0,0,1,1,1,2,2,2,},
{0,0,0,1,1,1,2,2,2,},
{0,0,0,1,1,1,2,2,2,},
{3,3,3,4,4,4,5,5,5,},
{3,3,3,4,4,4,5,5,5,},
{3,3,3,4,4,4,5,5,5,},
{6,6,6,7,7,7,8,8,8,},
{6,6,6,7,7,7,8,8,8,},
{6,6,6,7,7,7,8,8,8,},
};
int num,r[N],l[N],d[N],u[N],col[N],sz[M],head;
int a[10][10];
void remove(int p)
{
l[r[p]]=l[p],r[l[p]]=r[p];
for(int i=u[p];i!=p;i=u[i])
for(int j=r[i];j!=i;j=r[j])
u[d[j]]=u[j],d[u[j]]=d[j],--sz[col[j]];
}
void resume(int p)
{
l[r[p]]=r[l[p]]=p;
for(int i=u[p];i!=p;i=u[i])
for(int j=r[i];j!=i;j=r[j])
u[d[j]]=d[u[j]]=j,++sz[col[j]];
}
void link(int j)
{
++num;
u[num]=u[j];d[num]=j;col[num]=j;
u[d[num]]=d[u[num]]=num;++sz[j];
if(!head)head=num;
else l[num]=num-1,r[num-1]=num;
}
void make(int i,int j,int k)//i行,j列,填k
{
head=0;
link(i*9+j+1),link(81+i*9+k),link(162+j*9+k),link(243+g[i][j]*9+k);
l[head]=num;r[num]=head;
}
bool bk;
void dance()
{
if(bk)return ;
if(!r[0])
{
for(int i=1;i<=9;i++)
{
for(int j=1;j<=9;j++)
{
printf("%d",a[i][j]);
}
}
bk=true;return ;
}
int p=r[0],x,y;
for(int i=r[p];i;i=r[i])if(sz[i]<sz[p])p=i;
remove(p);
for(int i=u[p];i!=p;i=u[i])
{
if(0<col[i]&&col[i]<=81)x=col[i];
else if(81<col[i]&&col[i]<=162)y=col[i];
for(int j=r[i];j!=i;j=r[j])
{
remove(col[j]);
if(0<col[j]&&col[j]<=81)x=col[j];
else if(81<col[j]&&col[j]<=162)y=col[j];
}
a[(x-1)/9+1][(x-1)%9+1]=(y-1)%9+1;dance();if(bk)return ;
for(int j=r[i];j!=i;j=r[j])resume(col[j]);
}
resume(p);
}
char s[90];
int main()
{
while(scanf("%s",s))
{
if(s[0]=='e')break;
num=324;bk=false;//memset(r,0,sizeof(r));memset(l,0,sizeof(l)),memset(u,0,sizeof(u));
//memset(d,0,sizeof(d));head=0;memset(sz,0,sizeof(sz));memset(col,0,sizeof(col));
memset(sz,0,sizeof(sz));head=0;
for(int i=0;i<=num;i++)l[i]=i-1,r[i]=i+1,u[i]=d[i]=i;
l[0]=num;r[num]=0;
int len=0;
for(int i=0;i<9;i++)
{
for(int j=0;j<9;j++)
{
int x=s[len]-(s[len]=='.'?'.':'0');len++;
if(x)make(i,j,x);
else for(int k=1;k<=9;k++)make(i,j,k);
}
}
dance();puts("");
}
return 0;
}
POJ3076
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<cstdlib>
using namespace std;
const int g[20][20]=
{
{0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,},
{0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,},
{0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,},
{0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,},
{4,4,4,4,5,5,5,5,6,6,6,6,7,7,7,7,},
{4,4,4,4,5,5,5,5,6,6,6,6,7,7,7,7,},
{4,4,4,4,5,5,5,5,6,6,6,6,7,7,7,7,},
{4,4,4,4,5,5,5,5,6,6,6,6,7,7,7,7,},
{8,8,8,8,9,9,9,9,10,10,10,10,11,11,11,11},
{8,8,8,8,9,9,9,9,10,10,10,10,11,11,11,11},
{8,8,8,8,9,9,9,9,10,10,10,10,11,11,11,11},
{8,8,8,8,9,9,9,9,10,10,10,10,11,11,11,11},
{12,12,12,12,13,13,13,13,14,14,14,14,15,15,15,15,},
{12,12,12,12,13,13,13,13,14,14,14,14,15,15,15,15,},
{12,12,12,12,13,13,13,13,14,14,14,14,15,15,15,15,},
{12,12,12,12,13,13,13,13,14,14,14,14,15,15,15,15,},
};
const int N=1100;
const int M=17000;
int l[M],r[M],u[M],d[M],col[M],row[M],sz[N],num,head;
void remove(int p)
{
r[l[p]]=r[p];l[r[p]]=l[p];
for(int i=u[p];i!=p;i=u[i])
for(int j=r[i];j!=i;j=r[j])
u[d[j]]=u[j],d[u[j]]=d[j],--sz[col[j]];
}
void resume(int p)
{
r[l[p]]=l[r[p]]=p;
for(int i=u[p];i!=p;i=u[i])
for(int j=r[i];j!=i;j=r[j])
u[d[j]]=d[u[j]]=j,++sz[col[j]];
}
void link(int i,int j)
{
++num;
u[num]=u[j];d[num]=j;++sz[j];
u[d[num]]=d[u[num]]=num;col[num]=j;row[num]=i;
if(!head)head=num;
else l[num]=num-1,r[num-1]=num;
}
void make(int i,int j,int k)
{
int len=(i*16+j)*16+k;head=0;
link(len,i*16+j+1),link(len,256+i*16+k),link(len,512+j*16+k),link(len,768+g[i][j]*16+k);
l[head]=num;r[num]=head;
}
int ans[N],tot,a[21][21];char s[21][21];
bool dance(int k)
{
if(!r[0]){tot=k-1;return true;}
int p=r[0];
for(int i=r[p];i;i=r[i])if(sz[p]>sz[i])p=i;
remove(p);
for(int i=u[p];i!=p;i=u[i])
{
ans[k]=row[i];
for(int j=r[i];j!=i;j=r[j])remove(col[j]);
if(dance(k+1))return true;
for(int j=l[i];j!=i;j=l[j])resume(col[j]);
}
resume(p);
return false;
}
int main()
{
while(scanf("%s",s[0])!=EOF)
{
for(int i=1;i<16;i++)scanf("%s",s[i]);
num=1024;//memset(r,0,sizeof(r));memset(l,0,sizeof(l)),memset(u,0,sizeof(u));
//memset(d,0,sizeof(d));head=0;memset(sz,0,sizeof(sz));memset(col,0,sizeof(col));
memset(sz,0,sizeof(sz));//memset(h,-1,sizeof(h));
for(int i=0;i<=num;i++)l[i]=i-1,r[i]=i+1,u[i]=d[i]=i;
l[0]=num;r[num]=0;
for(int i=0;i<16;i++)
{
for(int j=0;j<16;j++)
{
int x=s[i][j]-(s[i][j]=='-'?'-':'A'-1);
if(x)make(i,j,x);
else for(int k=1;k<=16;k++)make(i,j,k);
}
}
dance(0);
for(int i=0;i<=tot;i++)
{
int x=(ans[i]-1)/16/16;
int y=(ans[i]-1)/16%16;
int c=(ans[i]-1)%16;
a[x][y]='A'+c;
}
for(int i=0;i<16;i++)
{
for(int j=0;j<16;j++)printf("%c",a[i][j]);
puts("");
}
puts("");
}
return 0;
}