您的位置:首页 > 编程语言 > C语言/C++

C语言中的数独问题(回溯)

2017-11-02 23:27 197 查看
描述:

数独游戏规则

在9阶方阵中,包含了81个小格(九列九行),其中又再分成九个小正方形(称为宫),每宫有九小格。

游戏刚开始时,盘面上有些小格已经填了数字(称为初盘),游戏者要在空白的小格中填入1到9的数字,

使得最后每行、每列、每宫都不出现重复的数字,而且每一个游戏都只有一个唯一的解答(称为终盘)。

输入:

一个9*9的矩阵,0表示该位置是空白。

输出:

一个9*9的矩阵,格式与输入类似。

输入样例:

900050060

020070100

300102040

703800529

000345000

516009403

050208006

007090010

030010004

输出样例:

971453268

428976135

365182947

743861529

892345671

516729483

154238796

687594312

239617854

1.这道题的输入很奇怪。如果一开始把数据输入到int型数组中,数组中就会有9个9位的数,而不是81个1位的数。所以只能把数据输入到字符型数组中,这样才能保证每次只读取一个数字。

2.用回溯法穷举二维数组时,不需要声明两个变量,只需要一个变量经过/和%运算就可以确定行和列。

3.在for循环后添加shudu[x][y]的必要。

和普通穷举不同,普通穷举时不需要考虑不同位置间数的关系;

和8皇后问题也不同,8皇后问题只需要考虑新加入的数和其左边其上边的数的关系;

数独问题中,每一个数和其前后左右的数都有关系。

所以一个位置在当前情况下取不到值时,应该在回溯前把该位置的值返回0,这样才不会影响其他数的取值,

相当于开始讨论一种新的情况。

如果不返回0,在讨论前面位置的其他情况时仍然会受这个位置的9的影响。

#include<stdio.h>
int shudu[9][9];
char temp[9][10];
void search(int m);
void output();
int check(int m);
int main()
{
for(int i=0;i<9;i++)
{
for(int j=0;j<=9;j++)
{
scanf("%c",&temp[i][j]);//每次只读取一个数字
if(temp[i][j]!='\n')
{
shudu[i][j]=temp[i][j]-'0';
}
}
}
search(0);
return 0;
}
void search(int m)
{
if(m>=1&&m<=81)
{
if(check(m-1)==0) return;
}
if(m==81)
{
output();
}
if(m>=0&&m<=80)
{
int x=m/9;
int y=m%9; //将m转化为二维数组的形式
if(shudu[x][y]!=0)//不再改变输入时确定的数(1-9)
{
search(m+1);
}
if(shudu[x][y]==0)//讨论空位(0)的可能取值
{
for(int i=1;i<=9;i++)
{
shudu[x][y]=i;
search(m+1);
}
shudu[x][y]=0;
/*和普通穷举不同,普通穷举时不需要考虑不同位置间数的关系;
和8皇后问题也不同,8皇后问题只需要考虑新加入的数和其左边其上边的数的关系;
数独问题中,每一个数和其前后左右的数都有关系。
所以一个位置在当前情况下取不到值时,应该在回溯前把该位置的值返回0,这样才不会影响其他数的取值,
相当于开始讨论一种新的情况。
如果不返回0,在讨论前面位置的其他情况时仍然会受这个位置的9的影响。*/
}
}
}
int check(int n)
{
int x=n/9;
int y=n%9;
int i,j;
for(i=0;i<=8;i++)//检查每列中不出现重复数字
{
if(i!=x&&shudu[i][y]==shudu[x][y]) return 0;
}
for(j=0;j<=8;j++)//检查每行中不出现重复数字
{
if(j!=y&&shudu[x][j]==shudu[x][y]) return 0;
}
int l=(x/3)*3,c=(y/3)*3;
for(i=l;i<=l+2;i++)
{
for(j=c;j<=c+2;j++)
{
if((i!=x||j!=y)&&shudu[i][j]==shudu[x][y]) return 0;//检查小九宫格中是否有重复数字
}
}
return 1;
}
void output()//输出
{
for(int i=0;i<9;i++)
{
for(int j=0;j<9;j++)
{
printf("%d",shudu[i][j]);
}
printf("\n");
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  c语言 数独 回溯