• 回溯法——数独游戏


    一、问题描述

    数独(Sudoku)是一款大众喜爱的数字逻辑游戏。玩家需要根据9X9盘面上的已知数字,推算出所有剩余空格的数字,并且满足每一行、每一列、每一个粗线宫内的数字均含1-9,并且不重复。
    输入:
    包含已知数字的9X9盘面数组[空缺位以数字0表示]
    输出:
    完整的9X9盘面数组

    输入示例:

    0 9 2 4 8 1 7 6 3
    4 1 3 7 6 2 9 8 5
    8 6 7 3 5 9 4 1 2
    6 2 4 1 9 5 3 7 8
    7 5 9 8 4 3 1 2 6
    1 3 8 6 2 7 5 9 4
    2 7 1 5 3 8 6 4 9
    3 8 6 9 1 4 2 5 7
    0 4 5 2 7 6 8 3 1

     输出示例:

    5 9 2 4 8 1 7 6 3
    4 1 3 7 6 2 9 8 5
    8 6 7 3 5 9 4 1 2
    6 2 4 1 9 5 3 7 8
    7 5 9 8 4 3 1 2 6
    1 3 8 6 2 7 5 9 4
    2 7 1 5 3 8 6 4 9
    3 8 6 9 1 4 2 5 7
    9 4 5 2 7 6 8 3 1

     二、思路

    对于这个题我们的第一思路当然是用深度遍历回溯法来完成。

    首先将数字存在9*9的二维数组数据结构内,其次寻找值为0的元素,将其换成1到9任一个数字。

      若能满足称为数独的三个条件,则继续往下搜索值为0的元素。

        同样将其换成0到9之间的任意数字,若发现所有的数字都不满足条件的话,则回溯到上一个点,并把该点的值继续换成其他数字。

      直到所有的81个点都遍历完,若遍历完发现没有满足条件的值可以填满值为0的位子,则返回False。

    三、代码实现

    首先我们先写一个函数来判断数字num是否可以放到9*9矩阵的(row,col)位置上。

    def check(matrix,row,col,value):
        """
        检测在(row,col)放value是否合适
        1.每行含1-9,不含重复值value
        2.每列含1-9,不含重复值value
        3.3*3区块含1-9,不含重复值value
        """
        #检测每行
        for j in range(9):
            if matrix[row][j]==value:
                return False
        #检测每列
        for i in range(9):
            if matrix[i][col]==value:
                return False
        # 检测元素所在3*3区域
        area_row=row//3*3
        area_col=col//3*3
        for i in range(area_row,area_row+3):
            for j in range(area_col,area_col+3):
                if matrix[i][j]==value:
                    return False
        return True

    然后我们就可以用回溯法来完成数独游戏了:

    def solveSudoku(matrix,count=0):
        """
        遍历每一个未填元素,遍历1-9替换为合适的数字
        """
        if count==81:#递归出口
            return True
        row=count//9#行标
        col=count%9#列标
        if matrix[row][col]!=0:#已填充
            return solveSudoku(matrix,count=count+1)
        else:#未填充
            for i in range(1,10):
                if check(matrix,row,col,i):#找到可能的填充数
                    matrix[row][col]=i
                    if solveSudoku(matrix,count=count+1):#是否可完成
                        return True#可完成
                    #不可完成
                    matrix[row][col]=0#回溯, i换个数继续走
            return False#不可完成
    
    matrix=[]
    for i in range(9):
        matrix.append(list(map(int,input().split())))
    # print(matrix)
    solveSudoku(matrix,0)
    # print(solveSudoku(matrix,0))
    # for i in range(9):
    #     print (' '.join(map(str,matrix[i])))
    # print(matrix)
    for li in matrix:
        print(' '.join(list(map(str,li))))

    这里值得注意的一点是,我们可以用递归函数来判断,若我们将当前点的值设为 i 时,其余点是否可以完成数独游戏,即:

    for i in range(1,10):
                if check(matrix,row,col,i):#找到可能的填充数
                    matrix[row][col]=i
                    if solveSudoku(matrix,count=count+1):#是否可完成
                        return True#可完成

    如果不能完成的话,则回溯,我们这里只需要将 matrix[row][col]设为0,然后让他接着遍历0-9中的其余数即可。

  • 相关阅读:
    在地址栏里输入一个地址回车会发生哪些事情
    ROS librviz库
    jumpserver运行源码
    django源码剖析(steup、runserver、生命周期)
    QT在linux下编译出现Unable to create a debugging engine错误的解决
    node 服务启动
    查看端口占用
    自定义reducer,pipe,compose函数 码农
    talk 码农
    实现简版redux和中件间 码农
  • 原文地址:https://www.cnblogs.com/sunny0824/p/13516415.html
Copyright © 2020-2023  润新知