迷宫问题的分析和回溯法解决

您所在的位置:网站首页 回溯法的特点有哪些方面呢英语 迷宫问题的分析和回溯法解决

迷宫问题的分析和回溯法解决

2024-07-11 12:59| 来源: 网络整理| 查看: 265

问题描述

来搜这个问题的肯定是对这个问题有一定的了解,在这里就简单讲一下什么是迷宫问题. 就是可以用一个二维数组来描绘一个迷宫,其中数字1(或者其他数字都可以,这个无所谓)代表四周的边界和迷宫中的障碍物,这个二维数组类似下图:

迷宫示意图 图中1表示的部分就是墙和障碍物,0都是可以通行的

现在给定一个起点和终点,来寻找起点到终点之间的路径,例如从arr[1][1]到arr[7][7],就是从左上方到右下方.

问题分析 要走迷宫就要先制定一个计划或者说是规则,要告诉计算机我们先往哪个方向进行寻找,如果走不通再向哪个方向进行寻找,这个很简单,就是先判断四周是否有障碍物,是否下一步要走的地方的值为1,如果为0可以向这个地方走一步,四个方向就是四次判断 除了判断四周是否是障碍物之外,还需要判断这个地方之前是否走过了,因为四个方向是都有可能判断一次的,如果不把已经走过的地方标记出来就会走重复了.这里把经过的点标记为2 此外,如果这个点走过了但是走不通,也应该被标记出来,下次就不要走这里了.这里将走不通的点标记为3,标记了3之后应该以退回回溯到原来的那个点,在进行下一个方向的寻找 执行上述操作之后,有了4种标记,0代表没有走过,可以进行尝试,1代表障碍物不能走,2代表走过了也不能走,3代表此路不通,我们每进入一个新的点时,都应该先判断当前点,是否为0,如果不是都应该退回原来的点进行下一个方向的尝试. 那么,最后的问题是,怎么判断我是否到了终点呢?先判断一下当前所在的位置吗?其实只需要判断终点的值是否为2就可以了,为2就说明终点已经走过了,就已经是找到终点了. 明确以上5点时我们发现,每次找寻下一个路径走不通时,就应该退回到原来的位置,而且,每次找路的操作都是一样的,所以我们可以通过递归来进行实现. 实现回溯的原理

经过上面的分析我们发现了一个很重要的问题,就是如果下一个点是障碍物或走不通或者走过了,就应该回到上一个点继续在其他方向寻找,递归可以解决这个问题. 以第一个图的迷宫为例,例如:如果我们从起点arr[1][1]的位置先向下寻找,是走不通的,因为下面是1.

我们先把(1,1)这两个数据作为坐标传递到方法里,首先判断(1,1)所在位置是否为0,显然是为0的可以继续向下走,这里我们自己调用自己,把下一个坐标传进方法,向下走就应该是(2,1),到了这一步发现当前二维数组的这个位置是1,应该退回,那么此时我们就让该方法返回,并且返回false,这样,我们就又退回到了第一个方法中,此时这个方法中的坐标还是(1,1)这个点,开始下一个方法的寻找.

大家都知道,在调用方法时其实是在方法栈中压入了一个新的栈帧,这个栈帧里的变量是独立的和原方法中的变量是两块区域.第一次调用方法时变量是(1,1),第二次调用方法时为(2,1),这只是代表在第二个方法中变量的值为(2,1),上一个方法变量仍为(1,1),当第二次执行的方法结束返回时,方法从方法栈上弹出,此时又回到了调用的位置处,即,回到了第一个方法,方法的变量又会到了(1,1),在使用这个变量进行下一个方向的寻找. 如下图所示: 执行方法变量变化 方法调用机制 此上就是实现回溯的机制.

代码实现 迷宫回溯代码 public class MiGong { /** * 迷宫回溯问题,递归调用自己 * 注意:方法栈中的每个栈帧中的IBegin个JBegin都是独立的,回到调用的方法的位置处时,进行了回溯 * IBegin和JBegin是调用方法时的值,就是说回到了原来的那两个值 * |i=2 j=2| * |i=1 j=2| * |i=2 j=1| * |i=1 j=1| * |_______| * @param map 地图 * @param iBegin 开始的行数 * @param jBegin 开始开始的列数 * @param iEnd 要寻找终点的行数 * @param jEnd 要寻找终点列数 * @return */ public boolean findWay(int[][] map , int iBegin , int jBegin , int iEnd , int jEnd){ if(map[iEnd][jEnd]


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3