算法之回溯法—-解决9宫格问题
最近一直在看算法,原因是马上的算法竞赛就要到来了,今天回顾了一下常用算法中的回溯法。
回溯法也是深度优先遍历的一种方法,不过在回溯法进行的同时,将不可能的结果直接pass掉,这样就大大提高了程序的效率,回溯法求解八皇后问题在网上是非常多的,我这里就不举例了,今天我们用回溯法来求解难倒很多数学家的9宫格问题。问题是这样的:
玩家需要根据9×9盘面上的已知数字,推理出所有剩余空格的数字,并满足每一行、每一列、每一个同色九宫内的数字均含1-9,不重复。
数独的答案都是唯一的,所以,多个解也称为无解。直接附上代码啦,便于大家一起分析。
#include<stdio.h>
int result=0; //多少种结果
void showsudu(int data[9][9])
{
result++;
for(int row=0;row<9;row++)
{
for(int col=0;col<9;col++)
{
printf("%d ",data[row][col]);
}
printf("\n");
}
printf("\n");
}
bool check(int data[9][9],int row,int col,int k) //判断是否可以将第row行、第col列的数设为k
{
int m,n;
for(n=0;n<9;n++) //判断行,是否有k
{
if(data[row][n] == k)
return false;
}
for(m=0;m<9;m++)
{
if(data[m][col] == k) //判断列,是否有k
return false;
}
int p=(row/3)*3,q=(col/3)*3; //下面判断所在小九宫格,是否有k
for(m=p;m<p+3;m++)
{
for(n=q;n<q+3;n++)
{
if(data[m][n] == k)
return false;
}
}
return true; //可行,返回true
}
void sudo(int data[9][9],int number) //data为81个格,编号0-80,number为第几个格
{
int temp[9][9];
int row,col;
for(row=0;row<9;row++)
{
for(col=0;col<9;col++)
temp[row][col]=data[row][col];
}
row=number/9; col=number%9; //求出第number个格对应的行数和列数
if(data[row][col] != 0) //已经有原始数据
{
if (number == 80) //是最后一个格子,输出独数
showsudu(temp);
else //不是最后一个格子,求下一个格子
sudo(temp,number+1);
}
else //else下面是没有数的情况
{
for(int k=1;k<=9;k++) //分别用1-9的数填格
{
if(check(temp,row,col,k)) //判断k是否可以填入第row行、第col列的格子
{
temp[row][col]=k; //n填入第row行、第col列的格子
if(number == 80)
showsudu(temp);
else
sudo(temp,number+1);
temp[row][col]=0; //恢复为0,循环用下一个k去尝试
}
}
}
}
int main()
{
/*int data[9][9]={
{0,0,5,3,0,0,0,0,0},
{8,0,0,0,0,0,0,2,0},
{0,7,0,0,1,0,5,0,0},
{4,0,0,0,0,5,3,0,0},
{0,1,0,0,7,0,0,0,6},
{0,0,3,2,0,0,0,8,0},
{0,6,0,5,0,0,0,0,9},
{0,0,4,0,0,0,0,3,0},
{0,0,0,0,0,9,7,0,0}}; //81个格
//*/
int data[9][9]={
{0,0,5,3,0,0,0,0,0},
{8,0,0,0,0,0,0,2,0},
{0,7,0,0,1,0,5,0,0},
{4,0,0,0,0,5,3,0,0},
{0,1,0,0,7,0,0,0,6},
{0,0,3,2,0,0,0,8,0},
{0,6,0,5,0,0,0,0,9},
{0,0,4,0,0,0,0,3,0},
{7,0,0,0,0,9,6,4,5}}; //81个格
/*printf("请输入数独中的原始数据,没有数据的用0代替。\n");
for(int row=0;row<9;row++)
{
printf("请输入第%d行的9个数:",row+1);
for(int col=0;col<9;col++)
scanf("%d",&data[row][col]);
}
printf("数独的解为:\n\n");
//*/
sudo(data,0); //开始填第1个格
if(result==0)
printf("此数独无解!\n");
else
printf("数独%d个解!\n",result);
return 0;
}