递归算法能够解决很多计算机科学问题,迷宫问题就是其中一个典型案例。本篇教程我们将采用递归算法求解迷宫问题,输出从入口到出口的所有迷宫路径。
01
用递归算法解决迷宫问题
迷宫问题在《数据结构教程》第3章介绍过,设mgpath(int xi,int yi,int xe,int ye,path)是求从(xi,yi)到(xe,ye)的迷宫路径,用path变量保存一条迷宫路径,它是元素为Box类型的ArrayList对象,其中Box类定义如下:
class Box //方块类
{ int i; //方块的行号int j; //方块的列号public Box(int i1,int j1) //构造方法{ i=i1;j=j1;}
}
当从(xi,yi)方块找到一个相邻可走方块(i,j)后,mgpath(i,j,xe,ye,path)表示求从(i,j)到出口(xe,ye)的迷宫路径。显然,mgpath(xi,yi,xe,ye,path)是“大问题”,而mgpath(i,j,xe,ye,path)是“小问题”(即大问题=试探一步+小问题),如下图所示。
▍大小问题的关系
求解上述迷宫问题的递归模型如下:
mgpath(xi,yi,xe,ye,path)将(xi,yi)添加到path中; 若(xi,yi)=(xe,ye)即找到出口
置mg[xi][yi]=-1;
输出path中的迷宫路径;
恢复出口迷宫值为0即置mg[xe][ye]=0
mgpath(xi,yi,xe,ye,path)将(xi,yi)添加到path中; 若(xi,yi)不是出口
置mg[xi][yi]=-1;
对于(xi,yi)每个相邻可走方块(i,j),调用mg(i,j,xe,ye,path);
path回退一步并置mg[xi][yi]=0;
上述递归模型中,对于方块(xi,yi),先添加到path末尾(所有path中的方块都是通道,所以初始调用时入口必须是通道),对于它的每一个相邻可走方块(i,j)都执行“小问题”mgpath(i,j,xe,ye,path),之后需要从(xi,yi)方块回退(删除path中的末尾方块)并置mg[xi][yi]为0,其目的是恢复前面求迷宫路径而改变的环境,以便找出所有的迷宫路径。以下图的迷宫为例:
▍迷宫示意图
求入口(1,1)到出口(4,4)所有迷宫路径的完整程序如下:
import java.lang.*;
import java.util.*;
class Box //方块类
{ int i; //方块的行号
int j; //方块的列号
public Box(int i1,int j1) //构造方法{ i=i1;j=j1;}
}
class MazeClass //求解迷宫路径类
{ final int MaxSize=20;
int [][] mg; //迷宫数组
int m,n; //迷宫行列数
int cnt=0; //累计迷宫路径数
public MazeClass(int m1,int n1) //构造方法{ m=m1;
n=n1;
mg=new int[MaxSize][MaxSize];
}
public void Setmg(int [][] a) //设置迷宫数组{ for (int i=0;i for (int j=0;j mg[i][j]=a[i][j];
}
void mgpath(int xi,intyi,intxe,intye,ArrayList path) //求解迷宫路径为:(xi,yi)->(xe,ye){ Box b;
int di,i=0,j=0;
b=new Box(xi,yi);
path.add(b); //将(xi,yi)添加到path中
mg[xi][yi]=-1; //mg[xi][yi]=-1
if (xi==xe&&yi==ye) //找到了出口,输出一个迷宫路径
{ System.out.printf("迷宫路径%d:",++cnt); //输出path中的迷宫路径
for (int k=0;k System.out.printf(" (%d,%d)",path.get(k).i,path.get(k).j);
System.out.println();
mg[xi][yi]=0; //恢复为0,否则别的路径找不到出口
}
else //(xi,yi)不是出口
{ di=0;
while (di<4) //处理(xi,yi)四周的每个相邻方块(i,j)
{ switch(di)
{
case 0:i=xi-1; j=yi; break;
case 1:i=xi; j=yi+1; break;
case 2:i=xi+1; j=yi; break;
case 3:i=xi; j=yi-1; break;
}
if (mg[i][j]==0) //(i,j)可走时
mgpath(i,j,xe,ye,path); //从(i,j)出发查找迷宫路径
di++; //继续处理(xi,yi)下一个相邻方块
}
}
path.remove(path.size()-1); //删除path末尾方格(回退一个方块)
mg[xi][yi]=0;
}
}
public class Exam5_5
{ public static void main(String[] args){ int [][] a= { {1,1,1,1,1,1},{1,0,1,0,0,1},
{1,0,0,1,1,1},{1,0,1,0,0,1},
{1,0,0,0,0,1},{1,1,1,1,1,1} };
MazeClassmz=new MazeClass(6,6);
ArrayList path=new ArrayList();
mz.Setmg(a);
mz.mgpath(1,1,4,4,path);
}
}
上述程序的执行结果如下:
迷宫路径1: (1,1) (2,1) (3,1) (4,1) (4,2) (4,3) (3,3) (3,4) (4,4)
迷宫路径2: (1,1) (2,1) (3,1) (4,1) (4,2) (4,3) (4,4)
本例算法求出所有的迷宫路径,可以通过路径长度比较求出最短迷宫路径(可能存在多条最短迷宫路径)。
02
视频讲解
视频教程如下:
03
源代码下载
关注微信公众号,后台回复关键词“迷宫问题”即可获得完整源代码。
【参考书籍】
《数据结构教程(Java语言描述)》
ISBN:978-7-302-55134-8
李春葆 编著
定价:69.8元
上一篇:
用Python写一个智力问答游戏 | 附代码+视频
利用神经网络实现股票预测 | 附代码