引言
在了解如何用python、lingo实现数独问题之前我们先了解什么是广度优先搜索、回溯,因为python实现数独问题是回溯算法的一个经典算法习题,也是python实现数独问题用到的主要算法。
前言
深度优先搜索是一种在开发爬虫早期使用较多的方法。它的目的是要达到被搜索结构的叶结点(即那些不包含任何超链的HTML文件) 。在一个HTML文件中,当一个超链被选择后,被链接的HTML文件将执行深度优先搜索,即在搜索其余的超链结果之前必须先完整地搜索单独的一条链。深度优先搜索沿着HTML文件上的超链走到不能再深入为止,然后返回到某一个HTML文件,再继续选择该HTML文件中的其他超链。当不再有其他超链可选择时,说明搜索已经结束。
回溯法(back tracking)(探索与回溯法)是一种选优搜索法,又称为试探法,按选优条件向前搜索,以达到目标。但当探索到某一步时,发现原先选择并不优或达不到目标,就退回到上一步,重新选择,这种走不通就退回再走的技术为回溯法,而满足回溯条件的某个状态的点称为“回溯点”。
上述两种方法其实本质上就是枚举法,只不过是一种有策略的枚举-----------------------------------------根据问题的约束条件进行剪枝。
目录
算法简介
回溯法
用数据结构中的树简单举一个例子:
从树的根节点开始,对每一个子树都有两种操作(取、不取)(取其中一个就要舍弃其余的子树),直到树的最后一层。其中的每个被取子树都可以看作是一次尝试,每次尝试都可以得出一个结果。将得到的结果综合起来,就是的所有可能的取法。
深度优先搜索
深度优先遍历图的方法是,从图中某顶点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)