数独问题之排除法和唯余法

关于数独的规则,在这里就不介绍了,蓝天十分钟内教你玩转数独对数独的规则和基本方法进行了解释。

这里主要介绍采用程序的方法来解数独问题。

数独问题最基本的方法是排除法和唯余法。

解数独问题,基本方法都是从数独满足的三个条件而得来的:

1、每行数字填入1-9,且不能重复 
2、每列数字填入1-9,且不能重复 
3、每宫数字填入1-9,且不能重复(宫就是黑粗线框出的3×3单元格的区域) 

所谓排除法,就是如果i行j列的位置的数字为d,那么i行、i列以及该位置所在的宫的其它位置不能有d的存在,否则就违背了数独的条件。

而唯余法则是用自己本身所在的行、列和宫的其它数字来得到自己可以放置的数字。

不过,应该注意的是,这些基本的方法只能解一些相对比较简单的题目。

排除法是用自己去排除其它格可以放置的数字,因此,就必须保存每个格被排除的数字。依次遍历81个格,如果某个格初始时已经填入了数字,就要用它来排除它所在行、列、宫可以放置的数字,行和列是很好判断的,关键的问题是宫,可以通过某个格获得该格所在的宫,然后依次遍历宫内的各个元素,这是通过in_square()来完成的。如果最后某个格被经过排除后只能放一个数字,那么,该位置就放置该数字。

唯余法是用别人来得到自己可以放置的数字,因此,必须保存每个格可以放置的数字。依次遍历81个格,如果某个宫初始时没有填入数字,就要用它所在的行、列、宫的其它数字来得到它可以放置的数字。其实代码跟上面的类似。

下面解释一下各数据结构和函数的功能:

char sudoku[MAXN][MAXN];    整个数独棋盘,这里为了简单起见,使用二维数组
int flag[MAXN][MAXN];              因为数独棋盘中,有些数字是固定的,保存一个二维数组用于标识这些数字。

                                                 当flag[i][j] = 0,说明sudoku[i][j]需要填入数字,如果flag[i][j] = 1,说明 sudoku[i][j]不需要填入数字。
char *exclude[89];                      包含89个指针的数组,每个指针保存某个格的排除的相关信息。

                                                  sudoku[i][j]对应的排除信息保存在exclude[i * 10 + j]中,它是一个包含9个元素的字符数组。exclude[i * 10 + j][k]保存的是sudoku[i][j]中是否可以放置k + 1,如果exclude[i * 10 + j][k] = 0表示可以放置k + 1,否则表示不能放置k + 1。

int empty_digit;                           记录未填入数字的个数,可以用于结束程序的条件。

以下就是数据结构的定义:

#define	MAXN	9
#define	TRI	3

char sudoku[MAXN][MAXN];
int flag[MAXN][MAXN];
char *left_digits[89];
cha

你可能感兴趣的:(数独)