zoukankan      html  css  js  c++  java
  • 回溯法——数独游戏

    一、问题描述

    数独(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中的其余数即可。

  • 相关阅读:
    百度之星资格赛1001——找规律——大搬家
    HDU1025——LIS——Constructing Roads In JGShining's Kingdom
    DP(递归打印路径) UVA 662 Fast Food
    递推DP UVA 607 Scheduling Lectures
    递推DP UVA 590 Always on the run
    递推DP UVA 473 Raucous Rockers
    博弈 HDOJ 4371 Alice and Bob
    DFS(深度) hihoCoder挑战赛14 B 赛车
    Codeforces Round #318 [RussianCodeCup Thanks-Round] (Div. 2)
    DP(DAG) UVA 437 The Tower of Babylon
  • 原文地址:https://www.cnblogs.com/sunny0824/p/13516415.html
Copyright © 2011-2022 走看看