一、迷宫回溯问题
1.问题
一个7*8的数组模拟迷宫,障碍用1表示,通路使用0表示,给定起点(1,1)和终点(6,5),要求给出起点到终点的通路
2.解题思路
- 首先,我们需要给程序一个寻向的基本策略,我们先假定寻向顺序为“下-右-上-左”,也就是说从起点出发,先往下走,往下走不通就往右.....以此类推
- 然后我们需要给走过的路一个标记,暂记为2
- 而当从一个方向走到一个只能原路返回的死胡同时,就给这段路标记为3
- 当抵达终点坐标(6,5)时程序结束
3.代码实现
3.1生成地图
1 | /** |
3.2 寻路逻辑的实现
对于这个寻路程序,我们可以看见,往四个方向走的过程实际上除了方向外动作上是一样的;而具体分析同一个方向,每走过一个坐标的动作也是一样的,我们对流程进行分析:
- 出发,先往下走,判断下一格有没有障碍(
int[x][y]==1
) - 如果没有障碍,就继续往下走,然后重复步骤1到碰到障碍为止
- 如果有障碍,就按“下-右-上-左”的顺序,换个方向,然后重复步骤1到碰到障碍为止
- 如果找到了(6,5)就结束
表现为代码实际上就是一个递归的过程:
- 找路是方法体
- 找到了(6,5)或者死胡同是终止条件
1 | /** |
3.3 运行结果
将findWay()
方法中的终止条件从map[6][5] == 2
换成其他坐标即可更换终点位置,
棋盘大小和障碍物位置不影响findWay()
方法寻路。
二、八皇后问题
1.问题
皇后问题,一个古老而著名的问题,是回溯算法的典型案例。该问题由国际西洋棋棋手马克斯·贝瑟尔于 1848 年提出:
在 8×8 格的国际象棋上摆放八个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行、同一列或同一斜线上,求有多少种摆法?
2.解题思路
首先,我们先使用一个长度为8数组来表示八皇后的摆放位置,数组下标+1即表示棋盘的第几行,数组下标对应的存放的数字+1即为棋盘的第几列。举个例子:
arr = {0,2,3,8,4,6,2,7}
其中,元素0下标为0,即表示第一行第一列;元素2下标为1,即表示第二行第三列......以此类推。
任意假设任意坐标分标为
(x1,y1),(x2,y2)
,也就是用数组表示为arr[x1]=y1,arr[x2]=y2
的两个皇后不允许在同一列,我们可以理解为:arr[x1] != arr[x2]
;而任意坐标的皇后不允许在同一斜线,即
(x2-x1)=(y2-y1)
,也就是斜率不应当相同,我们可以理解为:Math.abs(x2-x1) != Math.abs(arr[x2]-arr[x1])
(注:
Math.abs()
为求绝对值方法)
3.代码实现
3.1 检查摆放位置的代码实现
在前面明确了如何用数组表示位置,以及如何检查皇后是否允许摆放后,我们有如下代码:
1 | //表示皇后位置的数组 |
3.2 完整代码
接着我们需要考虑如何使用递归方法来做到以下效果:
使用一个方法遍历第n行的每一列,检查每一列是否可以放置皇后:
- 如果可以放置皇后,将位置出入arr[n]中,然后递归调用自己,传入n+1开始遍历下一行.....以此类推
- 如果不可以放置皇后,就跳过该列检查下一列,如果可以就重复步骤1
- 若n行中全部位置都不合适,则结束本层返回上一层n-1层,重复步骤1
- 如果最后n=8,即八个皇后全部放置完毕,记一次完成摆放,然后结束递归返回第一层,继续检查第一层的下一列
最终代码实现结果如下:
1 | /** |