Python(深度优先搜索+回溯)、lingo实现数独问题

引言

在了解如何用python、lingo实现数独问题之前我们先了解什么是广度优先搜索、回溯,因为python实现数独问题是回溯算法的一个经典算法习题,也是python实现数独问题用到的主要算法。

前言

深度优先搜索是一种在开发爬虫早期使用较多的方法。它的目的是要达到被搜索结构的叶结点(即那些不包含任何超链HTML文件) 。在一个HTML文件中,当一个超链被选择后,被链接的HTML文件将执行深度优先搜索,即在搜索其余的超链结果之前必须先完整地搜索单独的一条链。深度优先搜索沿着HTML文件上的超链走到不能再深入为止,然后返回到某一个HTML文件,再继续选择该HTML文件中的其他超链。当不再有其他超链可选择时,说明搜索已经结束。

回溯法(back tracking)(探索与回溯法)是一种选优搜索法,又称为试探法,按选优条件向前搜索,以达到目标。但当探索到某一步时,发现原先选择并不优或达不到目标,就退回到上一步,重新选择,这种走不通就退回再走的技术为回溯法,而满足回溯条件的某个状态的点称为“回溯点”。

上述两种方法其实本质上就是枚举法,只不过是一种有策略的枚举-----------------------------------------根据问题的约束条件进行剪枝。

目录

引言

前言

算法简介

回溯法

深度优先搜索

问题描述

数独问题

算法思路

代码实现

python实现如下

 ​​lingo实现如下


算法简介

回溯法

用数据结构中的树简单举一个例子:

从树的根节点开始,对每一个子树都有两种操作(取、不取)(取其中一个就要舍弃其余的子树),直到树的最后一层。其中的每个被取子树都可以看作是一次尝试,每次尝试都可以得出一个结果。将得到的结果综合起来,就是的所有可能的取法。

深度优先搜索

深度优先遍历图的方法是,从图中某顶点v出发:

(1)访问顶点v;

(2)依次从v的未被访问的邻接点出发,对图进行深度优先遍历;直至图中和v有路径相通的顶点都被访问;

(3)若此时图中尚有顶点未被访问,则从一个未被访问的顶点出发,重新进行深度优先遍历,直到图中所有顶点均被访问过为止。

问题描述

数独问题

数独(shù dú)是源自18世纪瑞士的一种数学游戏。是一种运用纸、笔进行演算的逻辑游戏。玩家需要根据9×9盘面上的已知数字,推理出所有剩余空格的数字,并满足每一行、每一列、每一个粗线宫(3*3)内的数字均含1-9,不重复  。

数独盘面是个九宫,每一宫又分为九个小格。在这八十一格中给出一定的已知数字和解题条件,利用逻辑和推理,在其他的空格上填入1-9的数字。使1-9每个数字在每一行、每一列和每一宫中都只出现一次,所以又称“九宫格”。

算法思路

1、搜索下一个空的子单元格。如果没有找到,那么我们已经解决了这个难题;如果有,则进行第2步。
2、通过迭代数字1-9 来猜测正确的数字,并参考已经确定的数字来检查它是否是一个合法的数字。
3、如果找到一个有效的数字,此时则将这个值放入该子单元格并重新执行步骤1,否则进行步骤4。
4、如果数字1-9均无效,则将上一个子单元格的值重置为 0,并继续迭代以查找下一个有效数字。

代码实现

python实现如下

data = [[0,4,7,0,5,0,0,0,8],[6,0,5,0,3,0,2,0,1],[0,0,0,7,0,6,0,3,0],[0,0,6,0,7,0,0,2,4],[9,0,0,8,0,4,0,0,6],[4,5,0,0,1,0,9,0,0],[0,1,0,5,0,2,0,0,0],[2,0,8,0,4,0,5,0,3],[5,0,0,0,9,0,7,1,0]]
def find(data):
    for i in range(len(data)):
        for j in range(len(data)):
            if data[i][j] == 0:
                return i,j
    else:
        return True

def conflect(num,curnode_x,curnode_y,min_x,max_x,min_y,max_y): #num为填入值,curnode_x为该值的x坐标,curnode_y为该值的y坐标,lim等表示范围
    exchange = True
    if num in data[curnode_x]:
        return False
    for l in range(len(data)):
        if num == data[l][curnode_y]:
            return False
    for z in range(min_x,max_x):
        for x in range(min_y,max_y):
            if num == data[z][x]:
                return False
    return exchange

def shudu(x,y,z):
    stack = []
    stack.append((x,y,z))
    while len(stack) > 0:
        if find(data) == True:
            return data
        x,y = find(data)
        for val in range(1,10):
            if conflect(val,x,y,(x//3)*3,(x//3)*3+3,(y//3)*3,(y//3)*3+3):
                stack.append((x,y,val))
                data[x][y] = val
                break
        else:
            while len(stack) > 0:
                print_val = stack.pop(-1)
                data[print_val[0]][print_val[1]] = 0
                for nu in range(print_val[2]+1,10):
                    if conflect(nu,print_val[0],print_val[1],(print_val[0]//3)*3,(print_val[0]//3)*3+3,(print_val[1]//3)*3,(print_val[1]//3)*3+3):
                        stack.append((print_val[0],print_val[1],nu))
                        data[print_val[0]][print_val[1]] = nu
                        break
                else:
                    continue
                break
for i in shudu(0,0,0):
    print(i)


 ​​lingo实现如下

  • 6
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
好的,以下是一个简单的 Lingo 程序,可以解数独: ``` -- 数独谜题(0 表示空格) puzzle = [[5, 0, 0, 0, 0, 0, 6, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 2], [0, 1, 9, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0]] -- 检查行是否合法 function check_row(puzzle, row, num) for i = 1 to 9 do if puzzle[row][i] = num then return false end if end for return true end -- 检查列是否合法 function check_col(puzzle, col, num) for i = 1 to 9 do if puzzle[i][col] = num then return false end if end for return true end -- 检查九宫格是否合法 function check_box(puzzle, row, col, num) box_row = int((row - 1) / 3) * 3 + 1 box_col = int((col - 1) / 3) * 3 + 1 for i = box_row to box_row + 2 do for j = box_col to box_col + 2 do if puzzle[i][j] = num then return false end if end for end for return true end -- 检查是否可以填入数字 function can_place(puzzle, row, col, num) return check_row(puzzle, row, num) and check_col(puzzle, col, num) and check_box(puzzle, row, col, num) end -- 查找下一个空格 function find_empty(puzzle) for i = 1 to 9 do for j = 1 to 9 do if puzzle[i][j] = 0 then return i, j end if end for end for return 0, 0 end -- 递归求解数独 function solve(puzzle) row, col = find_empty(puzzle) if row = 0 and col = 0 then return true end if for num = 1 to 9 do if can_place(puzzle, row, col, num) then puzzle[row][col] = num if solve(puzzle) then return true end if puzzle[row][col] = 0 end if end for return false end -- 显示数独谜题和解法 on mouseUp put "Puzzle:" && cr after msg repeat with i = 1 to 9 put puzzle[i] after msg put cr after msg end repeat put cr & "Solution:" & cr after msg solve(puzzle) repeat with i = 1 to 9 put puzzle[i] after msg put cr after msg end repeat end mouseUp ``` 程序中,首先定义了一个数独谜题(0 表示空格)。然后定义了检查行、列和九宫格是否合法的三个函数,以及检查是否可以填入数字的函数、查找下一个空格的函数和递归求解数独的函数。最后在 `on mouseUp` 事件中调用这些函数,显示数独谜题和解法。 运行程序后,点击鼠标即可看到数独谜题和解法。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

!continue!

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值