小明最近对数独着迷,在玩游戏的时候,计算机程序能够立刻的出答案,好奇的它想知道计算机是怎么得出结果的。数独的游戏规则是根据盘面上的已知数字推理出空格里的数字,要求每一行、每一列、每一个粗线格中均含1~9,且不重复。
面对这样的问题,没有像公式一样的直接解决方式,所以只能靠尝试。就像在走迷宫,没有地图没所以面对每一个岔路口都只能以探索的形式深入,一旦发现路线不对就返回岔路口,选择另一个分支。
把这个比喻用在数独上的话,每一个空格就是一个岔路口,而每一个岔路口都有9种选择。我们肯定末端有一个出口。那么从第一个岔路口出发。假设第1各空格种的数字:1不可以,2也不可以,3可以。
接下来假设第二个空格,1、2、3都不可以,4可以。
这样一直假设下去,如果盘面上的数字相互矛盾则改变上一格的数字,在次尝试,当我们到达最后一个空格并且成功填入数字时,即可输出答案。
注意:输出答案的前提是题目有解。如果题目有两个或更多答案,程序可输出所有答案。
注意:每一次假设后都要把格子还原回0,以便下一次假设时盘面上的数字不冲突。如果不归零,那么可能陷入死局后退回到第一个空格时,第二个空格里已经有了9,这会影响我们的判断。
最终代码:
class Solution():
def solveSudoku(self,board):
self.helper(board,0)
def helper(self,board,index):
if index >= 81: #如果盘面已满
self.printSolution(board) #输出结果
return #返回上一格
if board[index] == 0: #如果当前格为空格
for i in range(1,10): #依次假设1~9
if self.isValid(board,index,i): #如果假设成立
board[index] = i #填入数字
self.helper(board,index + 1) #继续假设
board[index] = 0
else: #如果当前格有已知数
self.helper(board,index + 1) #跳过此格
def printSolution(self,board): #输出结果
for i in range(0,81,9):
print(board[i:i+9])
def isValid(self,board,index,num): #isValid方法检查当前假设是否合理
row = index // 9 #当前格子的行数
column = index % 9 #当前格子的列数
for i in range(index + 9,81,9): #检查和同列(下方)的格子是否矛盾
if board[i] == num:
return False
for i in range(index - 9, -1, -9): #检查和同列(上方)的格子是否矛盾
if board[i] == num:
return False
for i in range(9 * row,9 * (row + 1)):#检查和同行的格子是否矛盾
if board[i] == num:
return False
for i in range(row - row % 3,3 + row - row % 3): #检查和同粗线格子是否矛盾
for j in range(column - column % 3,3 + column - column % 3):
if board[j + i * 9] == num:
return False
return True
Solution().solveSudoku([4,1,0,0,0,7,8,5,0,
8,0,6,0,0,0,0,0,9,
0,2,0,0,9,0,6,0,0,
0,0,4,0,0,0,0,1,2,
2,0,0,5,8,0,0,7,0,
0,0,0,0,0,0,5,0,0,
0,0,0,7,0,2,0,0,0,
0,0,8,0,1,0,0,0,0,
0,7,0,0,6,0,0,0,0]
)