数独是源自18世纪瑞士的一种数学游戏。是一种运用纸、笔进行演算的逻辑游戏。玩家需要根据9×9盘面上的已知数字,推理出所有剩余空格的数字,并满足每一行、每一列、每一个粗线宫(3*3)内的数字均含1-9,不重复。数独盘面是个九宫,每一宫又分为九个小格。在这八十一格中给出一定的已知数字和解题条件,利用逻辑和推理,在其他的空格上填入1-9的数字。使1-9每个数字在每一行、每一列和每一宫中都只出现一次,所以又称“九宫格”。给你这样一个九宫格,你能求出这个数独的解么?保证数独有唯一解
九阶标准数独:
字符代码:
#include<cstdio>
#include<cstdlib>
char a[10][10],tmp[5];
int f;
void print()
{
f=1;
printf("\nAnswer:\n");
for (int i=1;i<=9;++i)
{
for (int j=1;j<=9;++j) putchar(a[i][j]);
puts("");
}
return ;
}
void dfs(int x,int y)
{
if (f) return ;
if (x==10)
{
print();
return ;
}
if (a[x][y]!='0')
{
if (y==9) dfs(x+1,1);
else dfs(x,y+1);
}
else
{
bool s[10]={0};
for (int i=1;i<=9;++i) s[a[x][i]-'0']=1;
for (int i=1;i<=9;++i) s[a[i][y]-'0']=1;
int h1=x,h2=x,s1=y,s2=y;
while (h1%3!=1) h1--;
while (h2%3!=0) h2++;
while (s1%3!=1) s1--;
while (s2%3!=0) s2++;
for (int i=h1;i<=h2;++i)
for (int j=s1;j<=s2;++j)
s[a[i][j]-'0']=1;
for (int i=1;i<=9;++i)
if (!s[i])
{
a[x][y]=i+'0';
if (y==9) dfs(x+1,1);
else dfs(x,y+1);
a[x][y]='0';
}
}
}
int main()
{
for (int i=1;i<=9;++i)
{
for (int j=1;j<=9;++j) a[i][j]=getchar();
gets(tmp);
}
dfs(1,1);
return 0;
}
数字代码:
#include<cstdio> #include<cstdlib> int a[10][10],f; void print() { f=1; printf("\nAnswer:\n"); for (int i=1;i<=9;++i) { for (int j=1;j<=9;++j) printf("%d ",a[i][j]); puts(""); } return ; } void dfs(int x,int y) { if (f) return ; if (x==10) { print(); return ; } if (a[x][y]!=0) { if (y==9) dfs(x+1,1); else dfs(x,y+1); } else { bool s[10]={0}; // 横判断 for (int i=1;i<=9;++i) s[a[x][i]]=1; // 竖判断 for (int i=1;i<=9;++i) s[a[i][y]]=1; int h1=x,h2=x,s1=y,s2=y; // 寻找边界 while (h1%3!=1) h1--; while (h2%3!=0) h2++; while (s1%3!=1) s1--; while (s2%3!=0) s2++; // 宫判断 for (int i=h1;i<=h2;++i) for (int j=s1;j<=s2;++j) s[a[i][j]]=1; for (int i=1;i<=9;++i) if (!s[i]) { a[x][y]=i; if (y==9) dfs(x+1,1); else dfs(x,y+1); a[x][y]=0; } } } int main() { for (int i=1;i<=9;++i) for (int j=1;j<=9;++j) scanf("%d",&a[i][j]); dfs(1,1); return 0; }
n阶数独:
#include<cstdio> #include<cstdlib> int a[10][10],n,f; void print() { f=1; printf("\nAnswer:\n"); for (int i=1;i<=n;++i) { for (int j=1;j<=n;++j) printf("%d ",a[i][j]); puts(""); } return ; } void dfs(int x,int y) { /* for (int i=1;i<=n;++i) { for (int j=1;j<=n;++j) printf("%d ",a[i][j]); puts(""); } system("pause"); */ if (f) return ; if (x==n+1) { print(); return ; } if (a[x][y]!=0) { if (y==n) dfs(x+1,1); else dfs(x,y+1); } else { bool s[10]={0}; // 横判断 for (int i=1;i<=n;++i) s[a[x][i]]=1; // 竖判断 for (int i=1;i<=n;++i) s[a[i][y]]=1; int h1=x,h2=x,s1=y,s2=y,m1,m2; if (n==9) m1=3,m2=3; else if (n==6) m1=2,m2=3; // 寻找边界 while (h1%m1!=1) h1--; while (h2%m1!=0) h2++; while (s1%m2!=1) s1--; while (s2%m2!=0) s2++; // 宫判断 for (int i=h1;i<=h2;++i) for (int j=s1;j<=s2;++j) s[a[i][j]]=1; for (int i=1;i<=n;++i) if (!s[i]) { a[x][y]=i; if (y==n) dfs(x+1,1); else dfs(x,y+1); a[x][y]=0; } } } int main() { printf("read n:\n"); scanf("%d",&n); printf("read number:\n"); for (int i=1;i<=n;++i) for (int j=1;j<=n;++j) scanf("%d",&a[i][j]); dfs(1,1); return 0; }
速度更快的代码
#include<cstdio> char a[10][10],tmp[5]; int hang[10][10],lie[10][10],gong[5][5][10],f; void print() { f=1; for (int i=1;i<=9;++i) { for (int j=1;j<=9;++j) putchar(a[i][j]); puts(""); } return ; } void dfs(int x,int y) { if (f) return ; if (y==10) x++,y=1; if (x==10) { print(); return ; } if (a[x][y]!='0') dfs(x,y+1); else { bool s[10]; for (int i=1;i<=9;++i) if (!hang[x][i] && !lie[y][i] && !gong[(x-1)/3+1][(y-1)/3+1][i]) { a[x][y]+=i; hang[x][i]=1; lie[y][i]=1; gong[(x-1)/3+1][(y-1)/3+1][i]=1; dfs(x,y+1); a[x][y]-=i; hang[x][i]=0; lie[y][i]=0; gong[(x-1)/3+1][(y-1)/3+1][i]=0; } } } int main() { for (int i=1;i<=9;++i) { for (int j=1;j<=9;++j) a[i][j]=getchar(); gets(tmp); } for (int i=1;i<=9;++i) for (int j=1;j<=9;++j) hang[i][a[i][j]-'0']=1,lie[j][a[i][j]-'0']=1; for (int i=1;i<=9;i+=3) for (int j=1;j<=9;j+=3) for (int heng=i;heng<=i+2;++heng) for (int shu=j;shu<=j+2;++shu) gong[(i-1)/3+1][(j-1)/3+1][a[heng][shu]-'0']=1; dfs(1,1); return 0; }