引言
在了解如何用python、lingo实现八皇后问题之前我们先了解什么是广度优先搜索、回溯、递归,因为python实现八皇后问题是回溯算法的一个经典算法习题,也是python实现八皇后问题用到的主要算法。
前言
广度优先搜索(Breadth First Search)简称广搜或者 BFS,是遍历图存储结构的一种算法,既适用于无向图(网),也适用于有向图(网)。
回溯法(back tracking)(探索与回溯法)是一种选优搜索法,又称为试探法,按选优条件向前搜索,以达到目标。但当探索到某一步时,发现原先选择并不优或达不到目标,就退回到上一步,重新选择,这种走不通就退回再走的技术为回溯法,而满足回溯条件的某个状态的点称为“回溯点”。
上述两种方法其实本质上就是枚举法,只不过是一种有策略的枚举-----------------------------------------根据问题的约束条件进行剪枝。
递归的思想是把一个大型复杂问题层层转化为一个与原问题规模更小的问题,问题被拆解成子问题后,递归调用继续进行,直到子问题无需进一步递归就可以解决的地步为止。
目录
算法简介
回溯法
用数据结构中的树简单举一个例子:
从树的根节点开始,对每一个子树都有两种操作(取、不取)(取其中一个就要舍弃其余的子树),直到树的最后一层。其中的每个被取子树都可以看作是一次尝试,每次尝试都可以得出一个结果。将得到的结果综合起来,就是的所有可能的取法。
广度优先搜索(Breadth First Search)
搜索本质上就是枚举,只不过是一种有策略的枚举, 通常在搜索前,根据条件降低搜索规模、根据问题的约束条件进行剪枝、利用搜索过程中的中间解,避免重复计算这几种方法从而进行算法上的优化 。
递归
主要的难点:
1、如何将原问题转化为一个与原问题规模更小的问题。
2、递归的终止条件。
问题描述
八皇后问题
八皇后问题是以国际象棋为背景的问题:有八个皇后(可以当成八个棋子),如何在 8*8 的棋盘
中放置八个皇后,使得任意两个皇后都不在同一条横线、纵线或者斜线上。
算法思路
1.从棋盘的第一行、第一列开始,依次判断当前位置是否能够放置皇后。
判断的依据:新皇后与之前的所有行、列中的皇后所在位置进行比较,如果新皇后与之前的所有行、列中的皇后在同一行、同一列、同一条对角线上(两条对角线(正、负)),则判断不符合条件,继续检索后序位置。
2.如果该行中所有位置都不符合要求,则回溯到前一行,改变该皇后的位置,继续执行第一步进行探索。
3.如果试探到最后一行,则说明所有皇后位置摆放完毕,再回溯到前一行,改变该皇后的位置,继续执行第一步进行探索。
代码实现
python实现如下
def num_Eight_Empresses(num): #判断新皇后与之前的所有行、列中的皇后在同一行、同一列、同一条对角线上 ans = [] def conflect(stack,y_next): for i in stack: x1,y1=i[0],i[1] if y1 == y_next or abs(x1 - len(stack)) == abs(y1 - y_next): return False return True def Eight_Empresses(x1,y1): li = [[0 for i in range(8)] for i in range(9)] stack = [] stack.append((x1,y1)) li[x1][y1] = 1 while len(stack) > 0: if len(stack) == 8: #所有皇后位置摆放完毕 print(stack) #输出所有皇后的位置 ans.append(stack) #记录有多少种方式可以存放8个皇后 curnode = stack.pop(-1) #回溯到前一行 li[curnode[0]][curnode[1]] = 1 for i in range(8): li[curnode[0]+1][i] = 0 elif len(stack) == 0: break for j in range(8): if conflect(stack,j): if li[len(stack)][j] == 0: stack.append((len(stack),j)) break else: continue else: curnode = stack.pop(-1) li[curnode[0]][curnode[1]] = 1 for i in range(8): li[curnode[0]+1][i] = 0 for i in range(num): Eight_Empresses(0,i) #递归寻找满足条件的8个皇后的位置 return len(ans) print(num_Eight_Empresses(8))
lingo实现如下
因为lingo软件本身的限制,所以使用lingo进行求解,只能求出众多可行解中的一个可行解。