python算法之利用回溯算法解数独

利用回溯算法解数独

小明最近对数独着迷,在玩游戏的时候,计算机程序能够立刻的出答案,好奇的它想知道计算机是怎么得出结果的。数独的游戏规则是根据盘面上的已知数字推理出空格里的数字,要求每一行、每一列、每一个粗线格中均含1~9,且不重复。

问题求解:

面对这样的问题,没有像公式一样的直接解决方式,所以只能靠尝试。就像在走迷宫,没有地图没所以面对每一个岔路口都只能以探索的形式深入,一旦发现路线不对就返回岔路口,选择另一个分支。

把这个比喻用在数独上的话,每一个空格就是一个岔路口,而每一个岔路口都有9种选择。我们肯定末端有一个出口。那么从第一个岔路口出发。假设第1各空格种的数字:1不可以,2也不可以,3可以。
python算法之利用回溯算法解数独_第1张图片

接下来假设第二个空格,1、2、3都不可以,4可以。

这样一直假设下去,如果盘面上的数字相互矛盾则改变上一格的数字,在次尝试,当我们到达最后一个空格并且成功填入数字时,即可输出答案。

注意:输出答案的前提是题目有解。如果题目有两个或更多答案,程序可输出所有答案。

数独解题思路图:
python算法之利用回溯算法解数独_第2张图片

注意:每一次假设后都要把格子还原回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]
                     )




运行结果:
python算法之利用回溯算法解数独_第3张图片

你可能感兴趣的:(python算法)