549-广度优先遍历搜索迷宫路径-求最短路径

寻找迷宫最短路径

在迷宫里面怎么找最短的路径???
在这里插入图片描述

使用广度遍历迷宫路径搜索最短路径:

0 0 1 1 1 1
1 0 0 0 0 1
1 0 1 1 0 1
1 0 0 0 0 1
1 0 1 1 1 1
1 0 0 0 0 0

广度优先遍历求最短路径

在这里插入图片描述
如果(0,0)的值为1,则表示迷宫的路口是封住的,直接return掉。
如果(0,0)的值为0,则表示路口是通的,把0入队。
然后开启循环,如果队列不为空,看队头元素,它的右边能不能走,能走,则把右边元素入队,
在这里插入图片描述

然后还要看(0,0)元素的下边,左边,上边能不能走,不能走,这个(0,0)元素看处理完了,出队。
在这里插入图片描述

然后现在队头就是第一行的第二个元素了,然后先把它的左边,和(0,0)的右边修改为不能走,然后看这个元素右边能不能走,不能走,看下面能不能走,可以走,然后下面的元素就入队。
在这里插入图片描述

然后队头元素还要看它的左边能不能走,不能走,上面能不能走,不能走,然后处理完了,就出队。

在这里插入图片描述
此时的这个节点就是第二行第二个节点
然后看它右边能不能走,能走,右边元素入队。
在这里插入图片描述

现在新元素是队列的队尾。队头即原来的元素还要继续判断,把所有的方向能走的元素都入队,现在看它的下面能不能走,可以走,下面的元素也入队,
在这里插入图片描述
然后看左边能不能走,不能走,上面能不能走,不能走,然后出队。
在这里插入图片描述
现在的队头元素的第二行第三列的那个元素。队尾元素是第三行第二列的那个元素。
然后继续看队头元素,看它右边能不能走,能走,右边元素入队
在这里插入图片描述
它的下面,左边,上面都不能走。如果把这个队头元素出队。
在这里插入图片描述

现在的队头就是第三行的第二列元素,队尾元素就是第二行第四列的元素。
以此类推下去。
层层扩张
在这里插入图片描述
在队列里,当把一个节点入队以后,我们发现这个队尾元素如果就是右下角的节点,就证明迷宫通路了,走到右下角的节点了。
队列里记录的是所有节点的行走状态,但是前面节点已经出队了,不在队列中。
这个队列存在的问题的:
在这里插入图片描述

队列只能找最短路径。但是最短路径的路径信息记录不下来。
在这里插入图片描述
开辟多大的空间呢?我们只能使用最坏情况下的空间的大小去开辟。
开辟 行乘以列 的大小的数组
在这里插入图片描述
我们到达右下角的节点的时候,就是找到出口了,我们得在迷宫路径有哪些节点,我们要记录右下角的节点是从它左边这个节点过来的,怎么记录?
迷宫是二维数组,在内存上其实都是一维数组,所以我们把这个二维数组映射到下面这个一维数组当中。
在这里插入图片描述
二维数组映射到一维数组的下标的公式如下:
在这里插入图片描述
然后当前节点向哪个方向走,把这个信息记录一下,记在它要走到的那个节点对应的一维数组位置上,记录:当前节点是哪个节点来的。然后一直往前推,直到找到入口节点(0,0),最短迷宫路径的路径信息就出来了。
在这里插入图片描述

代码实现

#include <iostream>
#include <queue>
#include <vector>
using namespace std;

//定义方向
const int RIGHT = 0;
const int DOWN = 1;
const int LEFT = 2;
const int UP = 3;
const int WAY_NUM = 4;

//定义行走状态
const int YES = 4;
const int NO = 5;

//迷宫
class Maze
{
public:
	Maze(int row, int col)
		:_row(row)
		, _col(col)
	{
		_pMaze = new Node*[_row];//开辟迷宫二维数组 
		for (int i = 0; i < _row; ++i)
		{
			_pMaze[i] = new Node[_col];
		}

		//node._x*_row + node._y
		_pPath.resize(_row * _col);//辅助数组开辟空间 
	}

	void initNode(int x, int y, int val)//初始化为No 
	{
		_pMaze[x][y]._x = x;
		_pMaze[x][y]._y = y;
		_pMaze[x][y]._val = val;
		for (int i = 0; i < WAY_NUM; ++i)
		{
			_pMaze[x][y]._state[i] = NO;
		}
	}

	void setNodeState()//设置迷宫行走状态 
	{
		for (int i = 0; i < _row; ++i)
		{
			for (int j = 0; j < _col; ++j)
			{
				if (_pMaze[i][j]._val == 1)
				{
					continue;
				}

				if (j < _col - 1 && _pMaze[i][j + 1]._val == 0)
				{
					_pMaze[i][j]._state[RIGHT] = YES;
				}

				if (i < _row - 1 && _pMaze[i + 1][j]._val == 0)
				{
					_pMaze[i][j]._state[DOWN] = YES;
				}

				if (j > 0 && _pMaze[i][j - 1]._val == 0)
				{
					_pMaze[i][j]._state[LEFT] = YES;
				}

				if (i > 0 && _pMaze[i - 1][j]._val == 0)
				{
					_pMaze[i][j]._state[UP] = YES;
				}
			}
		}
	}

	void searchMazePath()//广度优先遍历搜索 
	{
		if (_pMaze[0][0]._val == 1)
		{
			return;
		}
		_queue.push(_pMaze[0][0]);//入口节点入队 

		while (!_queue.empty())//队列不为空 
		{
			Node front = _queue.front();//获取队头元素 
			int x = front._x;
			int y = front._y;

			//右方向
			if (_pMaze[x][y]._state[RIGHT] == YES)
			{
				_pMaze[x][y]._state[RIGHT] = NO;
				_pMaze[x][y + 1]._state[LEFT] = NO;
				//在辅助数组中记录一下节点的行走信息
				_pPath[x*_row + y + 1] = _pMaze[x][y];
				_queue.push(_pMaze[x][y + 1]);
				if (check(_pMaze[x][y + 1]))
					return;
			}

			//下方向
			if (_pMaze[x][y]._state[DOWN] == YES)
			{
				_pMaze[x][y]._state[DOWN] = NO;
				_pMaze[x + 1][y]._state[UP] = NO;
				_pPath[(x + 1)*_row + y] = _pMaze[x][y];
				_queue.push(_pMaze[x + 1][y]);
				if (check(_pMaze[x + 1][y]))
					return;
			}

			//左方向
			if (_pMaze[x][y]._state[LEFT] == YES)
			{
				_pMaze[x][y]._state[LEFT] = NO;
				_pMaze[x][y - 1]._state[RIGHT] = NO;
				_pPath[x*_row + y - 1] = _pMaze[x][y];
				_queue.push(_pMaze[x][y - 1]);
				if (check(_pMaze[x][y - 1]))
					return;
			}

			//上方向
			if (_pMaze[x][y]._state[UP] == YES)
			{
				_pMaze[x][y]._state[UP] = NO;
				_pMaze[x - 1][y]._state[DOWN] = NO;
				_pPath[(x - 1)*_row + y] = _pMaze[x][y];
				_queue.push(_pMaze[x - 1][y]);
				if (check(_pMaze[x - 1][y]))
					return;
			}

			//当前节点出队列
			_queue.pop();
		}
	}

	void showMazePath()//打印迷宫 
	{
		if (_queue.empty())
		{
			cout << "不存在一条迷宫路径!" << endl;
		}
		else
		{
			//回溯寻找迷宫路径节点
			int x = _row - 1;
			int y = _col - 1;
			for (;;)
			{
				_pMaze[x][y]._val = '*';
				if (x == 0 && y == 0)
					break;
				Node node = _pPath[x*_row + y];
				x = node._x;
				y = node._y;
			}

			for (int i = 0; i < _row; ++i)
			{
				for (int j = 0; j < _col; ++j)
				{
					if (_pMaze[i][j]._val == '*')
					{
						cout << "* ";
					}
					else
					{
						cout << _pMaze[i][j]._val << " ";
					}
				}
				cout << endl;
			}
		}
	}
private:
	//定义迷宫节点路径信息
	struct Node
	{
		int _x;
		int _y;
		int _val;//节点的值
		int _state[WAY_NUM];//记录节点四个方向的状态
	};

	//检查是否是右下角的迷宫出口节点
	bool check(Node &node)
	{
		return node._x == _row - 1 && node._y == _col - 1;
	}

	Node **_pMaze;//动态开辟二维数组 
	int _row;//行 
	int _col;//列 
	queue<Node> _queue;//广度遍历依赖的队列结构
	vector<Node> _pPath;//记录广度优先遍历时,节点的行走信息,辅助数组 
};

int main()
{
	cout << "请输入迷宫的行列数(例如:10 10):";
	int row, col, data;
	cin >> row >> col;

	Maze maze(row, col);//创建迷宫对象

	cout << "请输入迷宫的路径信息(0表示可以走,1表示不能走):" << endl;
	for (int i = 0; i < row; ++i)
	{
		for (int j = 0; j < col; ++j)
		{
			cin >> data;
			//可以初始化迷宫节点的基本信息
			maze.initNode(i, j, data);
		}
	}

	//开始设置所有节点的四个方向的状态
	maze.setNodeState();

	//开始从左上角搜索迷宫的路径信息了
	maze.searchMazePath();

	//打印迷宫路径搜索的结果
	maze.showMazePath();

	return 0;
}

在这里插入图片描述

  • 4
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

林林林ZEYU

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值