技术类电子书大放送:电子书
宽度优先搜索-----解决迷宫最短路径问题
一、关于宽度优先搜索的知识
1.深度优先搜索利用栈进行计算,因此一般场景中采用递归的方式实现。
2.宽度优先搜索则利用队列进行计算,搜索时首先将初始状态添加到队列里,此后从队列的最前端不断取出状态,
把从该状态可以转移到的状态中尚未访问过的部分加入队列,如此往复,直至队列被取空或者找到问题的解。
3.宽度优先搜索按照距开始状态由近及远的顺序搜索,因此可以很容易的用来求最短路径、最少操作之类问题的答案。
二、迷宫最短路径问题
输出:22
三、算法分析与实现
1.如果到目的点存在多条路径,那么通过BFS肯定是最短的那条路径最先到达目的点。
2.使用一个二维数组来记录从开始点到每个点的距离。该二维数组被初始化为max_value,当值不等于max_value时,说明该点已经被其他更短路径上 ‘爬虫’ 遍历过,不能重复遍历。
public class AlgorithmCenter200715
{
private char[,] _maze= {
{'#','S','#','#','#','#','#','#','.','#' },
{'.','.','.','.','.','.','#','.','.','#' },
{'.','#','.','#','#','.','#','#','.','#' },
{'.','#','.','.','.','.','.','.','.','.' },
{'#','#','.','#','#','.','#','#','#','#' },
{'.','.','.','.','#','.','.','.','.','#' },
{'.','#','#','#','#','#','#','#','.','#' },
{'.','.','.','.','#','.','.','.','.','.' },
{'.','#','#','#','#','.','#','#','#','.' },
{'.','.','.','.','#','.','.','.','G','#' }
};
private int _sx=0, _sy=1;//迷宫开始位置
private int _ex=9, _ey=8;//迷宫终点位置
private int _maxPath => int.MaxValue;
//向四个方向移动矩阵
private int[] _xMove = {0, 1,0,-1};
private int[] _yMove = {-1, 0,1,0};
/// <summary>
/// 计算迷宫中从开始节点到某个结束节点的最小距离
/// </summary>
/// <returns></returns>
public int CaluateMazeShortestPath()
{
int h = _maze.GetLength(0);
int w = _maze.GetLength(1);
//存储从开始位置到每个位置的举例
int[,] path=new int[h,w];
//初始化成最大值
path.InitToSameValue(int.MaxValue);
path[_sx, _sy] = 0;
//用于实现BFS的队列
Queue<Point> que = new Queue<Point>();
//先将开始点坐标存入队列
que.Enqueue(new Point(_sx,_sy));
while (que.Count > 0)
{
var p = que.Dequeue();
//如果发现已经到达目标点,那么不需要在遍历队列中的其他点,说明已经通过最短路径到达了这个点
if (_maze[p.X, p.Y] == 'G')
break;
//向四个方向移动
for (int i = 0; i < 4; i++)
{
int dx = p.X + _xMove[i];
int dy = p.Y + _yMove[i];
//当path[dx,dy]==int.MaxValue时说明该点还没有被遍历到
if (dx>=0&&dx<h&&dy>=0&&dy<w&&_maze[dx,dy]!='#'&&path[dx,dy]==int.MaxValue)
{
path[dx, dy] = path[p.X, p.Y] + 1;
que.Enqueue(new Point(dx,dy));
}
}
}
return path[_ex,_ey];
}
class Point {
public Point(int x, int y)
{
X = x;
Y = y;
}
public int X { get; set; }
public int Y { get; set; }
}
}
public static void InitToSameValue(this int[,] a,int v)
{
int h = a.GetLength(0);
int w = a.GetLength(1);
for (int i = 0, j = h - 1; i <= j;i++,j--)
{
for (int m = 0; m<w; m++)
{
a[i,m]= v;
a[j, m] = v;
}
}
}