数独(九宫格)的高效算法

      比较容易想到的是用回溯法,从第一个格子开始到最后一格,每个格子由1到9进行尝试,看能否填下去,不能就回头。思路简单,可是执行时间太长了。有没有更加高效的搜索算法了?当然有。
      我们仅需要改变搜索的顺序,或者说改变填数的方法。
     先将数字1分别填入1到9区域中,然后再将数字2填入1到9区域,重复该操作,直到所有空位都被填满为止。
     为什么这样就快了?因为先将一个数字成功填入9个区域的制约性,远远大于按顺序地从第一个填到最后一个格。假设第一行全是空的,在第一行的第一格填了数字1,然后假如在第二行填不下数字1,证明第一行的数字1填错了,这时通过回溯纠正它,最坏需要9!次。
但如果是一个个区域地填入数字1,当第二个1填不下时,马上就能回溯到上一个1去纠正它的位置了。
具体C语言源程序如下:
#include<stdio.h>
#include<string.h>
int quyu[4][4]={{0,0,0,0},
                        {0,1,2,3},
                        {0,4,5,6},
                        {0,7,8,9}};
int a[10][10],hang[10][10],lie[10][10],grid[10][10],sum;
int p[10][2]={{0,0},{1,1},{1,4},{1,7},{4,1},{4,4},{4,7},{7,1},{7,4},{7,7}};
//p[i][0]和p[i][1]数组记录第i个区域的左上角的横纵坐标
void init()
{
 int i,j,k;
 memset(hang,0,sizeof(hang));
 memset(lie,0,sizeof(lie));
 memset(grid,0,sizeof(grid));
 sum=0; 
 for(i=1;i<=9;i++)
 for(j=1;j<=9;j++) 
 {
   scanf("%d",&k);
   a[i][j]=k;
   if(k)
  {
    hang[i][k]=1;    //第i行填入k了
    lie[j][k]=1;       //第j列填入k了
    grid[quyu[(i-1)/3+1][(j-1)/3+1]][k]=1;  //  (i , j)所在区域填入k了
    sum++;
   }
 }
}
void outt()
{
 int i,j;
 for(i=1;i<=9;i++)
 {
  for(j=1;j<=8;j++) printf("%d ",a[i][j]);
  printf("%d\n",a[i][9]);
 }
}

void solve(int k1,int k2)  //将数字k1填入区域k2
{
  int x,y,i,j;
  if(sum==81) {outt();return;}  //数独全填好了就输出
  if(grid[k2][k1])   //区域k2中已有数字k1了
  {
   if(k2<9) solve(k1,k2+1); //填下一个区域
   else solve(k1+1,1); //填下一个数字
  }

  x=p[k2][0]; y=p[k2][1];

  for(i=x;i<=x+2;i++)
for(j=y;j<=y+2;j++)
if(a[i][j]==0 && hang[i][k1]==0 && lie[j][k1]==0) //第(i,j)格为空,且可填入k1
{
a[i][j]=k1;
sum++;
hang[i][k1] = lie[j][k1] = 1;

if(k2<9) solve(k1,k2+1); //填下一个区域
else solve(k1+1,1); //填下一个数字

a[i][j]=0;
sum--;
hang[i][k1] = lie[j][k1] = 0;
}
}

int main()
{
 init();
 solve(1,1);  //将数字1从区域1开始填起
 return 0;
}
  • 6
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
九宫格数独问题是一个经典的回溯算法问题。该问题的目标是在一个九宫格中填入数字,使得每一行、每一列和每一个九宫格内的数字都不重复。 回溯算法是一种递归算法,它尝试解决问题的所有可能的解,并返回最优解。在九宫格数独问题中,我们可以从左上角开始,逐行或逐列地填充数字。每当我们填充一个数字时,我们需要检查该数字是否已经出现在该行、该列或该九宫格中。如果是,则需要回溯并尝试其他数字。如果所有数字都尝试过了,但没有找到解决方案,则需要回溯到上一个节点并尝试其他数字。 在实现九宫格数独问题的回溯算法时,我们可以使用递归函数来遍历所有可能的解决方案。我们可以使用一个二维数组来表示九宫格,其中0表示需要填充数字的位置。在递归函数中,我们可以遍历每一个需要填充数字的位置,并尝试填充数字。如果填充的数字符合要求,则递归进入下一个需要填充数字的位置。如果填充的数字不符合要求,则需要回溯并尝试其他数字。 当递归函数遍历完所有需要填充数字的位置时,九宫格数独问题的解决方案就被找到了。如果在遍历过程中没有找到解决方案,则说明该问题无解。 总的来说,九宫格数独问题是一个经典的回溯算法问题。通过使用递归函数和回溯技术,我们可以遍历所有可能的解决方案,并找到最优解。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值