(1)题目
来源
题目描述
数独是根据 9×9 盘面上的已知数字,推理出所有剩余空格的数字,并满足每一行、每一列、每一个粗线宫内的数字均含 1−9 ,不重复。每一道合格的数独谜题都有且仅有唯一答案,推理方法也以此为基础,任何无解或多解的题目都是不合格的。
芬兰一位数学家号称设计出全球最难的“数独游戏”,并刊登在报纸上,让大家去挑战。
这位数学家说,他相信只有“智慧最顶尖”的人才有可能破解这个“数独之谜”。
据介绍,目前数独游戏的难度的等级有一到五级,一是入门等级,五则比较难。不过这位数学家说,他所设计的数独游戏难度等级是十一,可以说是所以数独游戏中,难度最高的等级。他还表示,他目前还没遇到解不出来的数独游戏,因此他认为“最具挑战性”的数独游戏并没有出现。
输入格式
一个未填的数独。
输出格式
填好的数独。
输入样例
8 0 0 0 0 0 0 0 0 0 0 3 6 0 0 0 0 0 0 7 0 0 9 0 2 0 0 0 5 0 0 0 7 0 0 0 0 0 0 0 4 5 7 0 0 0 0 0 1 0 0 0 3 0 0 0 1 0 0 0 0 6 8 0 0 8 5 0 0 0 1 0 0 9 0 0 0 0 4 0 0
输出样例
8 1 2 7 5 3 6 4 9 9 4 3 6 8 2 1 7 5 6 7 5 4 9 1 2 8 3 1 5 4 2 3 7 8 9 6 3 6 9 8 4 5 7 2 1 2 8 7 1 6 9 5 3 4 5 2 1 9 7 4 3 6 8 4 3 8 5 2 6 9 1 7 7 9 6 3 1 8 4 5 2
(2)思路
1.分析问题:分析已知和未知
本题难点在于标记已填过的数字,并确保每行每列每九宫格中数字不重样
标记行和列较为简单,第1个维度保存行数/列数,第2个维度保存填的数字
标记九宫格中数字较难,需要找规律
我们将九宫格画出来,并标上号,建立一个平面直角坐标系。
我们只要让每个九宫格里所有位置的坐标(粉色)都在九宫格的坐标(橙色)内,就可以了
找规律发现,(行坐标+2)/3==九宫格行坐标,(列坐标+2)/3==九宫格列坐标
试验一下:
(2.3)数字7,(2+2)/3=1,(3+2)/3=1,在(1,1)九宫格里
各位可以自行试一试
注意:若此方法太难理解,可以写9个判断来找这个数在哪个九宫格里
2.数据定义:已知和未知的取名和类型
a[10][10]:保存数独中的数
k:暂时保存相应a[i][j]所保存的数
f1[10][10]:标记每行中每个数字是否出现
f2[10][10]:标记每列中每个数字是否出现
f3[5][5][10]:标记每九宫格中每个数字是否出现
3.数据输入:输入已知
输入时标记,若有数,标记此行此列此九宫格中这个数字;若是0,标记也无妨(填入数字为1-9)
for(int i=1;i<=9;i++)
{
for(int j=1;j<=9;j++)
{
cin>>a[i][j];
k=a[i][j];
f1[i][k]=1;//标记
f2[j][k]=1;
f3[(i+2)/3][(j+2)/3][k]=1;
}
}
4.数据计算:数字建模+设计算法(函数部分)----x=行,y=列
先判断这个数独是否被填完,若填完则直接输出并结束程序(题目说有且仅有唯一答案)
再判断是否需要换行
然后判断这个位置有没有填数
if(x==9&&y==10)
{
for(int i=1;i<=9;i++)
{
for(int j=1;j<=9;j++) cout<<a[i][j]<<" ";//输出
cout<<endl;
}
exit(0);//结束所有函数
}
if(y==10) f(x+1,1);
if(a[x][y]!=0) f(x,y+1);
若没有,枚举1-9这些数,判断此行此列此九宫格中是否有这个数,没有则填数并标记
然后进行下一层
若下一层进行后返回了,说明此数不应填在此位置,清空标记,并若这个位置的数为0
else
{
for(int i=1;i<=9;i++)
{
if(f1[x][i]==0&&f2[y][i]==0&&f3[(x+2)/3][(y+2)/3][i]==0)
{
a[x][y]=i;//填数
f1[x][i]=1;f2[y][i]=1;f3[(x+2)/3][(y+2)/3][i]=1;//标记
f(x,y+1);//进行下一层
a[x][y]=0;//清标记
f1[x][i]=0;f2[y][i]=0;f3[(x+2)/3][(y+2)/3][i]=0;
}
}
}
(3)完整AC代码
#include<iostream>
using namespace std;
int a[10][10],f1[10][10],f2[10][10],f3[5][5][10];
void f(int x,int y)
{
if(x==9&&y==10)
{
for(int i=1;i<=9;i++)
{
for(int j=1;j<=9;j++) cout<<a[i][j]<<" ";
cout<<endl;
}
exit(0);
}
if(y==10) f(x+1,1);
if(a[x][y]!=0) f(x,y+1);
else
{
for(int i=1;i<=9;i++)
{
if(f1[x][i]==0&&f2[y][i]==0&&f3[(x+2)/3][(y+2)/3][i]==0)
{
a[x][y]=i;
f1[x][i]=1;f2[y][i]=1;f3[(x+2)/3][(y+2)/3][i]=1;
f(x,y+1);
a[x][y]=0;
f1[x][i]=0;f2[y][i]=0;f3[(x+2)/3][(y+2)/3][i]=0;
}
}
}
}
int main()
{
int k;
for(int i=1;i<=9;i++)
{
for(int j=1;j<=9;j++)
{
cin>>a[i][j];
k=a[i][j];
f1[i][k]=1;
f2[j][k]=1;
f3[(i+2)/3][(j+2)/3][k]=1;
}
}
f(1,1);
return 0;
}