递归 - 回溯算法与八皇后问题
1. 参考
- 《程序设计基础》9.2.6分书问题,9.2.7(八皇后问题)
- 知乎:一篇总结带你彻底搞透回溯算法!
2. 简要介绍
可以用走迷宫的方式去理解回溯,设想把你放在一个迷宫里,想要走出迷宫,最直接的办法是什么呢?没错,试。先选一条路走起,走不通就往回退尝试别的路,走不通继续往回退,直到走遍所有的路,并且在走的过程中你可以记录所有能走出迷宫的路线。
2.1 回溯与八皇后问题
在国际象棋中,皇后是最强大的一枚棋子,可以吃掉与其在同一行、列和斜线的敌方棋子。八皇后问题是这样一个问题:将八个皇后摆在一张8*8的国际象棋棋盘上,使每个皇后都无法吃掉别的皇后,一共有多少种摆法?
如果使用暴力穷举算法的话要在8*8个格子中选择8个格子来摆放皇后,一共要尝试 次,十亿级别的尝试次数!
稍加分析,我们可以得到一个不那么暴力的办法,显然,每行每列最多只能有一个皇后,如果基于这个事实进行暴力破解,那结果会好得多。安排皇后时,第一行有8种选法,一旦第一行选定,假设选为(1,i),第二行只能选(2,j),其中j!=i,所以有7种选法。以此类推,需要穷举的情况有8!=40320种。
我们先降下规模来看看4皇后问题:4个皇后在4*4的格子里各自安排不打架,一共有多少种安排方法?试着来穷举一下,真的需要4!=24次尝试吗?现在我们把第一个皇后放在第一个格子,被涂黑的地方是不能放皇后的。
Q | |||
第二行的皇后只能放在第三格或第四格,按照回溯我们要先尝试放在第三格,则:
Q | |||
Q | |||
这样第三位皇后无论放哪里都难逃被吃掉的厄运。于是在第一个皇后位于1号,第二个皇后位于3号的情况下问题无解。我们只能返回上一步来,给2号皇后换个位置。
Q | |||
Q | |||
显然,第三个皇后只有一个位置可选。当第三个皇后占据第三行蓝色空位时,第四行皇后无路可走,于是发生错误,返回上层调用(3号皇后),而3号也别无可去,继续返回上层调用(2号),2号已然无路可去,继续返回上层(1号),于是1号皇后改变位置如下,继续搜索。
Q | |||
代码方面,回溯算法的框架:
result = []
def try(路径, 选择列表):
if 满足结束条件:
result.add(路径)
return
for 选择 in 选择列表:
做选择
try(路径, 选择列表)
撤销选择