前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >迷宫问题的三种解法

迷宫问题的三种解法

作者头像
大忽悠爱学习
发布2021-11-15 10:19:45
4590
发布2021-11-15 10:19:45
举报
文章被收录于专栏:c++与qt学习

栈解决—深度优先遍历思想

代码语言:javascript
复制
#include<iostream>
using namespace std;
#include<stack>
#include<forward_list>
//迷宫 1为墙 0为通路
int Graph[][10] =
{
        {1,1,1,1,1,1,1,1,1,1},
		{1,0,0,1,0,0,0,1,0,1},
		{1,0,0,1,0,0,0,1,0,1},
		{1,0,0,0,0,1,1,0,0,1},
		{1,0,1,1,1,0,0,0,0,1},
		{1,0,0,0,1,0,0,0,0,1},
		{1,0,1,0,0,0,1,0,0,1},
		{1,0,1,1,1,0,1,1,0,1},
		{1,1,0,0,0,0,0,0,0,1},
		{1,1,1,1,1,1,1,1,1,1}
};
//迷宫 起点 终点
bool findPath(int (*Graph)[10],int x1,int y1,int x2,int y2)
{
	//记录迷宫路径的一维数组
	forward_list<pair<int, int>> path;
	//创建栈
	stack<pair<int, int>> s;
	//将入口加入栈中
	s.push({x1,y1});
	//设置入口点的经过标记
	Graph[x1][y1]= -1;
	//记录弹出栈顶的元素
	pair<int, int> top;
	//设置有没有找到可走的相邻的方块
	bool find = false;
	//设置方向--右 下 左 上
	int di = 0;
	//当栈不为空时
	while (!s.empty())
	{
		//弹出栈顶元素,判断是否为终点
		top=s.top();
		//如果走到迷宫终点就输出完整迷宫路径
		if (top.first == x2 && top.second == y2)
		{
			cout << "迷宫完整路径:" << endl;
			//将栈顶元素,挨个弹出放入path数组中
			while (!s.empty())
			{
				path.emplace_front(s.top());
				s.pop();
			}
			for (forward_list<pair<int, int>>::iterator it = path.begin(); it != path.end(); it++)
				cout << "{" << (*it).first << "," << (*it).second << "}" << endl;
			return true;
		}
		//如果没走到终点
	    //下面就要考虑,是不是要往四周某个方向前进,去寻找终点
		di = 0;//每一次到了一个新的点,要往它四周探测,都要将方向归0
		find = false;//还未找到新的可走方向
		int row, c;//行 列
		while (di < 4)//四个方向还没有都探测完
		{
			switch (di)//右 下 左 上
			{
			case 0:
			{
				c=top.second+1;
				row= top.first;
				break;
			}
			case 1:
			{
				row=top.first+1;
				c = top.second;
				break;
			}
			case 2:
			{
				c=top.second-1;
				row = top.first;
				break;
			}
			case 3:
			{
				row=top.first-1;
				c = top.second;
				break;
			}
			}
			if (Graph[row][c] == 0)//表示有通路
			{
				s.push({ row,c });
				Graph[row][c] = -1;
				find = true;
				break;
			}
			//没有通路,就再探测其他方向
			di++;
		}
		//如果四个方向探测完,方向四个方向都无法通过,就要弹出栈顶元素,进行回退操作
		if (find == false&&di==4)
		{
			s.pop();
		}
	}
	return false;//没找到终点
}
 
int main()
{
	findPath(Graph, 1,1,8,8);
	system("pause");
	return 0;
}
在这里插入图片描述
在这里插入图片描述

队列解决------广度优先遍历—找到最短路径

在这里插入图片描述
在这里插入图片描述
代码语言:javascript
复制
#include<iostream>
using namespace std;
#include<vector>
#include<queue>
#include<stack>
//迷宫 1为墙 0为通路
int Graph[6][6] =
{
{ 1,1,1,1,1,1},
{ 1,0,1,1,1,1},
{ 1,0,1,0,1,1},
{ 1,0,0,0,1,1},
{ 1,1,0,0,0,1},
{ 1,1,1,1,1,1},
};
struct elm
{
	pair<int, int> pos;//当前位置
	int pre;//前驱
	int cur;//当前位置
};
//迷宫 起点 终点
bool findPath(int (*Graph)[6],int x1,int y1,int x2,int y2)
{
      //记录最短路径的数组
	vector<elm> path;
	//队列
	queue<elm> q;
	//将起点加入队列
	elm e = { {x1,y1},-1,0 };//起点的前驱是-1,当前位置为0
	q.push(e);
	//设置经过的标记
	Graph[x1][y1] = -1;
	//方向
	int di = 0;
	//是否存在新的方向可以走
	bool find = false;
	//记录终点的前驱
	int endPre;
	//记录当前队列已经插入的元素个数
	int num = 0;
	//如果队列不为空
	while (!q.empty())
	{
		//对头元素放入path数组中
		path.push_back(q.front());
		//出队
		e = q.front();
		q.pop();
		//如果找到出口就结束循环
		if (find)
		{
			cout << "最短路径为:" << endl;
			vector<elm>::reverse_iterator it = path.rbegin();
			stack<elm> s;
			for (; it != path.rend(); it++)
			{
				if ((*it).cur == endPre)
				{
					s.push(*it);
					endPre = (*it).pre;
				}
			}
			while (!s.empty())
			{
				cout << "{" << s.top().pos.first << "," << s.top().pos.second << "}" << endl;
				s.pop();
			}
			cout << "{" << x2 << "," << y2 << "}" << endl;
			return true;
		}
		//将对头元素,四周能走的点全部按顺序依次加入队列
		di = 0;
		int row, c;
		while (di < 4)//右 下 左 上
		{
			switch (di)
			{
			case 0:
			{
				c = e.pos.second+1;
				row=e.pos.first;
				break;
			}
			case 1:
			{
				c = e.pos.second;
				row = e.pos.first+1;
				break;
			}
			case 2:
			{
				c = e.pos.second-1;
				row = e.pos.first;
				break;
			}
			case 3:
			{
				c = e.pos.second;
				row = e.pos.first-1;
				break;
			}
			}
			//判断当前方向是否为通路
			if (Graph[row][c] == 0)
			{
				num++;
				//获取当前要走方向的左标,判断是否可以走通
				//并且该点的前驱是刚刚出队的元素
				elm el = { {row,c},e.cur,num};
				//当前点入队
				q.push(el);
				//设置走过的标记
				Graph[row][c] = -1;
				//判断当前方向是否等于终点
				if (row == x2 && c == y2)
				{
					endPre = e.cur;
					find = true;
					break;
				}
			}
			di++;
		}
	
	}
	cout << "没找到出口" << endl;
	return false;//没找到出口
}
 
int main()
{
	findPath(Graph, 1,1,4,4);
	system("pause");
	return 0;
}
在这里插入图片描述
在这里插入图片描述

递归解决—求解全部路径

代码语言:javascript
复制
#include<iostream>
using namespace std;
#include<vector>
//迷宫 1为墙 0为通路
int Graph[][6] =
{
		 {1, 1, 1, 1, 1, 1},
		{1, 0, 0, 0, 1, 1},
		{1, 0, 1, 0, 0, 1},
		{1, 0, 0, 0, 1 ,1},
		{1, 1, 0, 0, 0, 1},
		{1, 1, 1, 1, 1, 1}
};
//迷宫 起点 终点
void findPath(int(*Graph)[6], int x1, int y1, int x2, int y2)
{
	int i, j;
	static vector<pair<int, int>> path;
	if (x1 == x2 && y1 == y2) 
	{
		//将终点坐标进入路径中 
		path.push_back({ x1,y1 });

		cout << "迷宫路径如下:" << endl;
		for (int i = 0; i < path.size(); i++)
		{
			cout << "{" << path[i].first << "," << path[i].second << "}" << endl;
		}
	}
	else {
		if (Graph[x1][y1] == 0) {
			int di = 0;	//用于四个方位移动的变量
			while (di < 4) {
				//第一步:将(xi,yi)进入path路径中 
				path.push_back({ x1,y1 });

				//对四个方位寻找相邻方块 
				switch (di) {
				case 0: {i = x1, j = y1+1; break; }
				case 1: {i = x1+1, j = y1; break; }
				case 2: {i = x1, j = y1-1; break; }
				case 3: {i = x1-1, j = y1; break; }
				}

				//第二步:将mg[xi][yi]=-1,避免来回走动 
				Graph[x1][y1] = -1;

				//第三步:递归调用迷宫函数求解小问题 
				findPath(Graph, i, j, x2, y2);

				//第四步:回退path数组中的元素,并将回退元素mg[xi][yi]=0来寻找其他路径 
				path.pop_back();
				Graph[x1][y1] = 0;
				di++;
			}
		}
	}
}

int main()
{
	findPath(Graph, 1, 1, 4, 4);
	system("pause");
	return 0;
}
在这里插入图片描述
在这里插入图片描述
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2021/04/15 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 栈解决—深度优先遍历思想
  • 队列解决------广度优先遍历—找到最短路径
  • 递归解决—求解全部路径
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档