回溯法
策略
我认为回溯法的策略可以当做蛮力法策略的延伸。当使用蛮力法解决问题时,我们会遍历所有可能的解,并且这种遍历的起始点是一样的。以走迷宫为例,如果我们使用蛮力法,将面临走不通就要完全从头走的情况。但是玩过迷宫游戏的人可能明白,在“试错”的过程中没有必要完全从头走,而是无路可走时,就返回上一步去做不同的选择,直观上就可以明白这更节约时间。
回溯法的基本策略就是这种更聪明的试错,即用“返回上一步”代替“完全从头走”。
算法流程
- 从一个起始点出发
- 选择下一步(不重复)
- 如果无解则回退到上一步
- 重复步骤2、3直到获得解或者遍历完解空间
使用条件
我认为与蛮力法类似,回溯法具有一般性,所以并没有什么特殊的使用条件,只要解空间可以在有限时间内遍历即可。
举例——4皇后问题
问题描述
国际象棋中的4皇后可以沿任意方向走任意距离,问有几种摆法使得4个皇后在4x4的棋盘上互相不能吃。
问题分析
这个问题明显可以使用蛮力法遍历求解,因此也可以用回溯法求解;再考虑一般更优的方法:(网上一谈及4皇后就是回溯法,当然没有错,只是在自己思考新问题时,应该在多个可能的算法中调研,如果有人一眼能看穿回溯法比较优,当我没说:/ )
考虑下贪心法,先不证明最优子结构和贪心选择性质,假设使用贪心法,我们就需要设定一个“贪心”的选择条件,似乎只能设为做选择时与前面所有皇后比较了,跟蛮力法没有区别。
在考虑其他方法之前,我想到,这个问题不能用贪心,从问题特点上来看会不会是因为这个问题没有最优子结构之类的条件呢?当我们摆好3个皇后,第4个皇后就确定了(因为这个问题棋盘大小和皇后数量的特殊性),得,还能再考虑。
考虑动态规划,我认为与贪心法的考虑类似,当摆好3个,剩余1个就确定了,同样在3个中,摆好2个剩余1个也确定了,因此在这个问题上用动态规划和蛮力法没有区别。
特别提醒:以上分析过程只经过短暂的思考,没有任何实际求证,思考过程也不注重严谨,仅做记录。
因此最后还是用回溯法解决咯。
算法设计
因为皇后可以八处乱走,所以我们直接假设在最后的解中每个皇后占1行(占1列同理)。
- 从第一行出发
- 考虑下一行
- 考虑当前行是否有位置与确定的行不冲突
- 全冲突就返回上一行并更新位置
- 重复步骤2、3、4
程序设计(python)
import numpy as np
# 4