题目描述
数独是根据9×9盘面上的已知数字,推理出所有剩余空格的数字,并满足每一行、每一列、每一个粗线宫内的数字均含1-9,不重复。每一道合格的数独谜题都有且仅有唯一答案,推理方法也以此为基础,任何无解或多解的题目都是不合格的。
芬兰一位数学家号称设计出全球最难的“数独游戏”,并刊登在报纸上,让大家去挑战。
这位数学家说,他相信只有“智慧最顶尖”的人才有可能破解这个“数独之谜”。
据介绍,目前数独游戏的难度的等级有一道五级,一是入门等级,五则比较难。不过这位数学家说,他所设计的数独游戏难度等级是十一,可以说是所以数独游戏中,难度最高的等级他还表示,他目前还没遇到解不出来的数独游戏,因此他认为“最具挑战性”的数独游戏并没有出现。
输入输出格式
输入格式:
一个未填的数独
输出格式:
填好的数独
输入输出样例
输入样例#1:
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
输出样例#1:
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
思路:一道搜索回溯题,在没填的空中逐个尝试填入1~9,如果已知条件判断不了再回溯。
对于行、列中出现过的数,设置一个布尔变量。
在这里可以用flag记录当前已放置数字的个数,每次放一个flag就++,这样当flag=9*9(81)时,说明已经放满了,输出即可。
代码如下:
-
#include <bits/stdc++.h>//万能头文件 using namespace std;//使用标准命名空间 int flag=0;当前已放置数字的个数 int num[9][9]={0};//存放原始数据 int x[9][9]={0};//标记这一行是否有重复的 int y[9][9]={0};//标记这一列是否有重复的 bool inspect(int i,int j,int dj)//检查当前这个数字是否在九宫格中有重复 { for(int ii=0;ii<3;ii++) { for(int jj=0;jj<3;jj++) { if(num[i+ii][j+jj]==dj)//在这个九宫格出现过,返回值为伪 { return 0; } } } return 1;//否则是真 } void out()//输出 { for(int i=0;i<9;i++) { for(int j=0;j<9;j++) { cout<<num[i][j]; } cout<<endl; } } void dfs(int flag) { if(flag==9*9)//如果所有空都被填满,传入输出结果函数,输出结果 { out(); return;//返回 } else { if(num[flag/9][flag%9]!=0)//此空非0,已经填好数了 { dfs(flag+1);//跳过 } else//如果是空位,填数 { for(int i=1;i<=9;i++) { if((x[flag/9][i-1]==0)&&(y[flag%9][i-1]==0)&&(inspect(flag/9,flag%9,i)))//行、列、九宫格中都没有重复,可以填数了 { num[flag/9][flag%9]=i;//把i放入数组 x[flag/9][i-1]=1;//在当前行已经使用过i了 y[flag%9][i-1]=1;//在当前列也已经使用过i了 dfs(flag+1);//搜索下一个 num[flag/9][flag%9]=0;//下面回溯 x[flag/9][i-1]=0; y[flag%9][i-1]=0; } } } } } int main() { int i,j; for(i=0;i<9;i++) { for(j=0;j<9;j++) { scanf("%d",&num[i][j]); if(num[i][j]) { x[i][num[i][j]-1]=1;//此数在本行中已经出现过了,要标记一下 y[j][num[i][j]-1]=1;//此数在本列中已经出现过了,要标记一下 } } } dfs(0);//调用函数 return 0; }