题目描述
数独是根据 9 × 9 9 \times 9 9×9 盘面上的已知数字,推理出所有剩余空格的数字,并满足每一行、每一列、每一个粗线宫内的数字均含 1 − 9 1 - 9 1−9 ,不重复。每一道合格的数独谜题都有且仅有唯一答案,推理方法也以此为基础,任何无解或多解的题目都是不合格的。
芬兰一位数学家号称设计出全球最难的“数独游戏”,并刊登在报纸上,让大家去挑战。
这位数学家说,他相信只有“智慧最顶尖”的人才有可能破解这个“数独之谜”。
据介绍,目前数独游戏的难度的等级有一到五级,一是入门等级,五则比较难。不过这位数学家说,他所设计的数独游戏难度等级是十一,可以说是所以数独游戏中,难度最高的等级。他还表示,他目前还没遇到解不出来的数独游戏,因此他认为“最具挑战性”的数独游戏并没有出现。
输入格式
一个未填的数独。
输出格式
填好的数独。
思路
我们使用dfs,然后进行剪枝,因为我们可以认为有且仅有一个解,所以一旦找到解即可退出,还有,我们想想自己做数独(尽管并没有做出来)的时候,尽量选择最少的来进行尝试,所以我们可以选择最小可能值的个数的点进行尝试,具体使用状压(2进制9位记录是否可以尝试的数字)
code:
#include<cstdio>
#include<queue>
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
int a[10],b[10],c[10],d[10]={
1,2,4,8,16,32,64,128,256,0};
int f[9][9],s,op[512],r[512];
bool o;
void dfs(int xx)
{
if (o==1) return;
if (xx==s)
{
o=1;
return;
}
int x,y,z=10;
for (int i=0;i<9;i++) for (int j=0;j<9;j++)
{
if (f[i][j]==-1&&op[a[i]&b[j]&c[i/3*3+j/3]]<=z)
{
z=op[a[i]&b[j]&c[i/3*3+j/3]];
if (z==0)
{
return;
}
x=i,y=j;
}
}
for (int k=a[x]&b[y]&c[x/3*3+y/3];k;k-=k&-k)
{
f[x][y]=r[k&-k];
a[x]^=d[f[x][y]],b[y]^=d[f[x][y]],c[x/3*3+y/3]^=d[f[x][y]];
dfs(xx+1);
if (o==1) return;
a[x]^=d[f[x][y]],b[y]^=d[f[x][y]],c[x/3*3+y/3]^=d[f[x][y]];
}
f[x][y]=-1;
return;
}
int main()
{
for (int i=0;i<9;i++) r[d[i]]=i;
for (int i=0;i<512;i++)
{
int i2=i;
for (;i2;i2-=i2&-i2) op[i]++;
}
s=0;
o=0;
for (int i=0;i<9;i++) a[i]=b[i]=c[i]=511;
for (int i=0;i<9;i++) for (int j=0;j<9;j++)
{
cin>>f[i][j];
f[i][j]-=1;
a[i]^=d[f[i][j]],b[j]^=d[f[i][j]],c[i/3*3+j/3]^=d[f[i][j]];
if (f[i][j]<0) s++;
}
dfs(0);
for (int i=0;i<9;i++)
{
for (int j=0;j<9;j++) cout<<f[i][j]+1<<' ';
cout<<endl;
}
return 0;
}