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++用深度优先搜索解数独问题的主要内容,如果未能解决你的问题,请参考以下文章

解数独(Python)

回溯算法和解数独

深度优先搜索(续)

在 C++ 中实现深度优先搜索

DFS数独游戏

广度优先搜索和深度优先搜索