C++用深度优先搜索解数独问题
Posted 青少年编程时间
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C++用深度优先搜索解数独问题相关的知识,希望对你有一定的参考价值。
数独是一种有趣的数字游戏,起源于18世纪初瑞士数学家欧拉等人研究的拉丁方阵,后来几经发展,引入日本,成为一种风靡全球的数字游戏。目前有专门的数独网站,数万玩家每日在进行挑战,然而,对于计算机而言,这并不是什么问题,用我们的方法可以很快求出所有的解。
数独就是一个9宫格的方阵,这个方阵有9行,有9列,同时又把它分成9个部分,如下图。
在这个方阵上,我们预先填有一部分已经确定的数字,要求玩家在空余的方格中填写数字,要求满足1~9每个数字在每一行只能用1次,在每一列也只能用1次,在图中用红笔标识出来的9个区域中也只能用一次。
如下图:
计算机解决这类问题,通常可以用穷举的方法,逐一尝试,但因为次数太多,时间较长,我们用深度优先搜索的方法进行必要的剪枝,以提高速度。
#include<bits/stdc++.h>
using namespace std;
int i,j,a[11][11],n;
bool k(int x,int y,int n)
{
for(int i=1;i<=9;i++)
if(a[x][i]==n)return 0;
for(int i=1;i<=9;i++)
if(a[i][y]==n)return 0;
for(int i=(x-1)/3*3+1;i<=(x-1)/3*3+3;i++)
{
for(int j=(y-1)/3*3+1;j<=(y-1)/3*3+3;j++)
if(a[i][j]==n) return 0;
}
return 1;
}
//以上为判断部分,我们需要进行三种情况的判断,同一行未放置该数,同一列未放置该数,同一区域中未放置该数。
void printa()
{
for(int i=1;i<=9;i++)
{
for(int j=1;j<=9;j++)cout<<a[i][j]<<" ";
cout<<endl;
}
exit(0);
}
一旦搜索到了第10行,说明已经找到了正确的解,我们就停止搜索,输出正确的解。
void dfs(int x,int y)
{
if(x==10) printa();
if(a[x][y]==0)
{
for(int n=1;n<=9;n++)
if(k(x,y,n)==1)
{
a[x][y]=n;
if(y==9) //如果已经搜索了第9列的话,下面搜索下一行的第一格子。
dfs(x+1,1);
else
dfs(x,y+1);
a[x][y]=0;
}
}
else
if(y==9)
dfs(x+1,1);
else
dfs(x,y+1);
}
int main()
{
for(i=1;i<=9;i++)
for(j=1;j<=9;j++)
cin>>a[i][j];
dfs(1,1);
return 0;
}
上述代码在判断部分明显很浪费时间,我们可以通过开设布尔型变量去减少判断的时间,代码如下:
#include<bits/stdc++.h>
using namespace std;
int a[11][11];
bool h[11][11],l[11][11],g[11][11];
void printa(){
for(int i=1;i<=9;i++){
for(int j=1;j<=9;j++)
cout<<a[i][j]<<" ";
cout<<endl;
}
exit(0);
}
void dfs(int x,int y){
if(x==10) printa();
if(a[x][y]!=0)
{
if(y==9)
dfs(x+1,1);
else
dfs(x,y+1);
}
if (a[x][y]==0)
for(int i=1;i<=9;i++)
{
if(h[x][i]&&l[y][i]&&g[(x-1)/3*3+(y-1)/3+1][i])
{
h[x][i]=false;
l[y][i]=false;
g[(x-1)/3*3+(y-1)/3+1][i]=false;
a[x][y]=i;
//cout<<x<<" "<<y<<endl;
if(y==9) dfs(x+1,1); else dfs(x,y+1);
a[x][y]=0;
h[x][i]=true;
l[y][i]=true;
g[(x-1)/3*3+(y-1)/3+1][i]=true;
}
}
}
int main()
{
memset(h,true,sizeof(h));
memset(l,true,sizeof(l));
memset(g,true,sizeof(g));
for(int i=1;i<=9;i++)
for(int j=1;j<=9;j++)
{
cin>>a[i][j];
if (a[i][j]!=0)
{
h[i][a[i][j]]=false;
l[j][a[i][j]]=false;
g[(i-1)/3*3+(j-1)/3+1][a[i][j]]=false;
}
}
dfs(1,1);
return 0;
}
这道题的解法很多,也可以用其它方法去解。
如果我的分析有错误或者不科学、不完整的地方,或者是有任何的疑问或者建议,或者是有什么思路或者方法,可以添加我的微信,也可以在留言区留言。
长按二维码,添加我的微信
以上是关于C++用深度优先搜索解数独问题的主要内容,如果未能解决你的问题,请参考以下文章