数独(すうどく,Sūdoku),是源自18世纪瑞士发明,流传到美国,再由日本发扬光大的一种数学游戏。是一种运用纸、笔进行演算的逻辑游戏。玩家需要根据9×9盘面上的已知数字,推理出所有剩余空格的数字,并满足每一行、每一列、每一个粗线宫内的数字均含1-9,不重复。
上机笔试题目描述如下:
数独是一个我们都非常熟悉的经典游戏,运用计算机我们可以很快地解开数独难题,现在有一些简单的数独题目,请编写一个程序求解。
输入9行,每行为空格隔开的9个数字,为0的地方就是需要填充的。
输出九行,每行九个空格隔开的数字,为解出的答案。解题思路:此题与dfs(深度优先搜索)问题有相似之处,所有的空格单元可以看作图的节点,遍历所有节点,从1~9之间选取数值填充,然后判断是否符合数独规则,若符合向更深一层遍历,否则返回上一层继续判断其他数值,并清除深层更新的数值,这个搜索方法是利用递归方法实现的,也是一种暴利解决方案,不多对于计算机而言这点计算不是难事,仍然保持较高的时间效率。具体的程序代码如下所示:
#include
#include
#include
using namespace std;
/* run this program using the console pauser or add your own getch, system("pause") or input loop */
vector > blank;
//int a[9][9];
int a[9][9] = {
{7,2,6,9,0,4,0,5,1},
{0,8,0,6,0,7,4,3,2},
{3,4,1,0,8,5,0,0,9},
{0,5,2,4,6,8,0,0,7},
{0,3,7,0,0,0,6,8,0},
{0,9,0,0,0,3,0,1,0},
{0,0,0,0,0,0,0,0,0},
{9,0,0,0,2,1,5,0,0},
{8,0,0,3,0,0,0,0,0}
};
int candidate[9]={1,2,3,4,5,6,7,8,9};
void printsoduku(){
for(int i=0;i<9;i++){
for(int j=0;j<9;j++){
cout< }
cout< }
cout< //该行没有问题
for(int i=0;i<9;i++){
if(a[x][i]==a[x][y]&&i!=y)
return false;
}
//该列没有问题
for(int i=0;i<9;i++){
if(a[i][y]==a[x][y]&&i!=x)
return false;
}
//该九宫格没有问题
for(int i=x/3*3;i for(int j=y/3*3;j if(a[i][j]==a[x][y]&&(i!=x||j!=y))
return false;
}
}
return true;
}
void clearblank(int depth){
for(int i=depth-1;i a[blank[i].first][blank[i].second]=0;
}
}
void dfs(pair pos,int depth){
for(int i=0;i<9;i++){
a[pos.first][pos.second]=candidate[i];//逐个测试所有候选值
bool pass=judge(pos.first,pos.second);
if(pass)
{
if(depth==blank.size()){
printsoduku();
//exit(0);
}
if(depth dfs(blank[depth],depth+1);
}
clearblank(depth);//将深度遍历更新的空白值复原为0
}
}
int main(int argc, char** argv) {
// 输入二维数组
// for(int i=0;i<9;i++){
// for(int j=0;j<9;j++){
// cin>>a[i][j];
// }
// }
printsoduku();
//统计数组中为0的元素的横纵坐标,保存到blank容器中
for(int i=0;i<9;i++){
for(int j=0;j<9;j++){
if(a[i][j]==0){
blank.push_back(make_pair(i,j));
}
}
}
//深度优先搜索,遍历所有的空白之处,并填写测试
dfs(blank[0],1) ;
return 0;
}
实验结果如下:
回顾这道题,关键点在于将数独的空白格遍历问题与图数据结构的深度优先搜索遍历问题联系起来,利用递归函数的方法,记录之前访问的节点在出现异常时及时返回同时复原改变的节点值。以上方法为暴利解决方法,优化方法则是缩小每个空白节点的候选集合范围,动态更新每个空白节点的候选值集合,然后逐个元素代入测试数据表的准确与否。判定规则类似于本文中的judge方法,即每行每列每个9宫格都不能出现重复的数字。