【数据结构Note3】- 栈 应用栈求解迷宫路径

news2024/11/29 20:34:56

文章目录

  • 栈求解迷宫路径
    • 1. 求解迷宫思想和难点
    • 2. 定义迷宫
    • 3. 定义方向结构体和数组
    • 4. 迷宫路径穷举
    • 5. 代码总测试

栈求解迷宫路径

本文分为两部分,第一部分让大家整体了解栈求解迷宫路径的整体思路和算法实现,第二部分仔细分析迷宫求解过程。小白门看不懂第一部分没关系,可以直接跳到下一部分,从定义迷宫开始往后看。

1. 求解迷宫思想和难点

求解迷宫路径整体思路就是穷举所有路径。从点出发,按某一方向探索,沿途在经过的位置设下标记。若能走通即某处可以到达。若该点所有方向均没有通路,则原返回,直到有路可走。如此循环直到到达终点,或无路可走返回起点。求解过程会用一个栈path存储迷宫路径上的所有有效坐标。

求解开始时,path栈首先存储起点坐标,此时栈顶就是起点坐标。内部循环,不断根据栈顶坐标(也就是当前坐标)和迷宫图得到下一步行走方向。

  • 有路可走则将下一个坐标入栈作为当前坐标,进入下一个循环。
  • 如果无路可走则出栈返回前一个结点,换方向尝试

求解迷宫穷举路径的难点就在于,如何在原路返回前一个点查找路径时不会重复的到达某点,形成死循环?

  1. 方案一是另外设置一标志数组 flag[n],其所有元素都初始化为0,一旦到达了某点(ij)之后,将对应flag]置1,下次再试探该位置时,因为已经置1了,就不能再选它了;缺点时有些浪费空间了撒
  2. 方案二是当到达某点(i,j)后将对应maze[i][j]置-1,其他未到达过的点其值只能是1或0,可与未到达过的点区别开来。这里采用方案二实现算法。

整体了解完迷宫求解算法,下面便是重点分析了

2. 定义迷宫

image-20221016112303375

如上图,对于长M,宽N的迷宫,需要在迷宫周围围上墙。所以定义的迷宫,我们用二级指针maze来表示迷宫,对应的为 mazeSample[M + 2][N + 2],整个迷宫图内部0标识通路,1表示围墙。

//定义迷宫数组的长宽M,N
const int M = 8;
const int N = 8;

//定义并初始化迷宫二维数组
int mazeSample[M + 2][N + 2] =
{
    {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}
};

int** maze = (int**)malloc(sizeof(int*) * (M+2));
for (int i = 0; i < M+2; i++)
{
    maze[i] = (int*)malloc(sizeof(int) * (N+2));
}
for (int i = 0; i < M+2; i++)
{
    for (int j = 0; j < N+2; j++)
    {
        maze[i][j] = mazeSample[i][j];
    }
}
//输出迷宫
for (int i = 0; i < M+2; i++)
{
    for (int j = 0; j < N+2; j++)
    {
        cout << maze[i][j]<<" ";
    }
    cout << endl;
}

image-20221019150408850

3. 定义方向结构体和数组

定义direct数组,数组元素为Direction结构体。Direction结构体存储两个整型变量,incX和intY分别表示该方向xy方向的增量。

当前坐标cur为:(x,y)

cur下一步移动的方向为:direct[v]

下一步的坐标next为:(x+direct[v].incX,y+direct[v].incY)

image-20221016112839084

上图中数组从上往下分别对应下右上左四个方向

//定义方向结构体
struct Direction
{
    //incX和intY分别表示该方向xy方向的增量
	int incX, incY;
};
//共四个方向,定义存储四个结构体的数组
Direction direct[4] = { {0,1},{1,0},{0,-1},{-1,0} };

//定义点坐标
struct pointer{
    int x;
    int y;
};

4. 迷宫路径穷举

路径存储在pointer类型的storage栈中。

迷宫路径穷举函数findPath的实现思路是:将起点压入栈storage中,不断根据getDirection函数寻找下一个合适的坐标,并将坐标压入栈中,再将其迷宫对应数值设为-1,防止重复穷举路径。如果没有合适坐标,说明当前是死胡同,则出栈,在前一个坐标寻找新路径。具体如下:

//根据当前结点获得下一步方向,返回整数temp,对应direct[temp]即为方向。若返回值则说明无路可走为
int getDirection(int** maze, pointer cur)
{
	int index = 0;
	while (index < 4)
	{
		//判断迷宫中direct[index]对应的方向是否可以走,可以则返回index作为下一步方向标识
		if (cur.x + direct[index].incX<N+1
			&& cur.y + direct[index].incY<M+1
			&&maze[cur.x + direct[index].incX][cur.y + direct[index].incY] == 0)return index;
		index++;
	}
	return 4;
}

//求解迷宫的函数,如果迷宫有解,就返回true。如果没解就返回false
bool findPath(int** maze, stack<pointer>& s)
{
	pointer cur;
	cur.x = 1;
	cur.y = 1;//cur就是起点
	maze[cur.x][cur.y] = -1;//将到过的位置设置为-1,防止重复穷举

	s.push( cur);
	while (!s.empty())
	{
		pointer top = s.top();
		if (top.x == 8 && top.y == 8)
		{
			return true;//判断是否是终点,是则成功并返回true
		}

		int direction = getDirection(maze,top);//根据栈顶拿到下一步方向direction

		if (direction == 4)//direction == 4说明无路可走
		{
			s.pop();//无路可走出栈,根据前一个结点找新路径
		}
		else
		{
			top.x += direct[direction].incX;
			top.y += direct[direction].incY;//根据方向更新当前坐标
			maze[top.x][top.y] = -1;//将到过的位置设置为-1,防止重复穷举
			s.push(top);
		}
	}
	return false;
}

5. 代码总测试

输出路径对应的坐标(逆序,栈先进后出)

image-20221019152254466
#include<iostream>
#include<Stack>
using namespace std;

//定义方向结构体
struct Direction
{
	int incX, incY;
};
//定义存储四个结构体的数组,每个元素对应一个方向
Direction direct[4] = { {0,-1},{0,1},{-1,0},{1,0} };
//定义迷宫数组的长宽M,N
const int M = 8;
const int N = 8;

//迷宫中坐标
struct pointer
{
	int x, y;//表示迷宫中位置的横纵坐标
};

//根据当前结点获得下一步方向,返回整数temp,对应direct[temp]即为方向。若返回值则说明无路可走为
int getDirection(int** maze, pointer cur)
{
	int index = 0;
	while (index < 4)
	{
		//判断迷宫中direct[index]对应的方向是否可以走,可以则返回index作为下一步方向标识
		if (cur.x + direct[index].incX<N+1
			&& cur.y + direct[index].incY<M+1
			&&maze[cur.x + direct[index].incX][cur.y + direct[index].incY] == 0)return index;
		index++;
	}
	return 4;
}

//求解迷宫的函数,如果迷宫有解,就返回true。如果没解就返回false
bool findPath(int** maze, stack<pointer>& s)
{
	pointer cur;
	cur.x = 1;
	cur.y = 1;//cur就是起点
	maze[cur.x][cur.y] = -1;//将到过的位置设置为-1,防止重复穷举

	s.push( cur);
	while (!s.empty())
	{
		pointer top = s.top();
		if (top.x == 8 && top.y == 8)
		{
			return true;//判断是否是终点,是则成功并返回true
		}

		int direction = getDirection(maze,top);//根据栈顶拿到下一步方向direction

		if (direction == 4)//direction == 4说明无路可走
		{
			s.pop();
		}
		else
		{
			top.x += direct[direction].incX;
			top.y += direct[direction].incY;//根据方向更新当前坐标
			maze[top.x][top.y] = -1;//将到过的位置设置为-1,防止重复穷举
			s.push(top);
		}
	}
	return false;
}

int main()
{

	//定义并初始化迷宫二维数组
	int mazeSample[M + 2][N + 2] =
	{
		{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}
	};

	int** maze = (int**)malloc(sizeof(int*) * (M+2));
	for (int i = 0; i < M+2; i++)
	{
		maze[i] = (int*)malloc(sizeof(int) * (N+2));
	}
	for (int i = 0; i < M+2; i++)
	{
		for (int j = 0; j < N+2; j++)
		{
			maze[i][j] = mazeSample[i][j];
		}
	}
	for (int i = 0; i < M+2; i++)
	{
		for (int j = 0; j < N+2; j++)
		{
			cout << maze[i][j]<<" ";
		}
		cout << endl;
	}
	stack<pointer> storage;
	findPath(maze, storage);
	cout << endl;
	int num = 0;
	while (!storage.empty())
	{
		pointer p = storage.top();
		cout << "(" << p.x << "," << p.y << ")";
		num++;
		if (num % 4==0)cout << endl;
		storage.pop();
	}
	
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/85058.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【机器视觉】电脑连接相机配置的二三事

最近手上有个机器视觉项目&#xff0c;现场总是反馈相机拍照取图是取的上一次的图&#xff0c;折腾很久&#xff0c;发现是配置的锅&#xff0c;这里记录下&#xff0c;防止下次再犯。 1.设置网卡固定IP&#xff1a; 举例&#xff1a;第一个网口&#xff1a;100.100.100.100 …

数据可视化 数据分析 常用图 seaborn

本文主要介绍几种数据分析阶段常用的统计图&#xff0c;可以用来验证数据分布&#xff0c;发现数据之间的关系&#xff0c;或进行异常值检测等。 import numpy as np import pandas as pd import matplotlib.pyplot as plt import seaborn as sns from scipy import stats im…

机器学习 集成学习

集成学习 参考机器学习——集成算法。 集成算法是指构建多个学习器&#xff0c;然后通过一定策略结合它们来完成学习任务&#xff0c;常常可以表现得比单一学习更显著优越。 集成算法一般分为三类&#xff1a; bagging。并行训练多个模型&#xff0c;预测结果取所有模型的投票…

list模拟实现

文章目录list的介绍list和vector的对比**list和vector对于排序算法速度的比较****list和vector对于迭代器的比较****list的模拟实现****框架****节点****迭代器****普通迭代器-普通写法****const 迭代器-普通写法****迭代器-高级写法****链表结构****关于节点的析构****关于迭代…

模型交易平台|金融大数据项目案例模型分享

股市评论数据情感分析 涉及关键技术&#xff1a; TF-IDF; 词嵌入; LSTM 主要工具&#xff1a;Python 技术大类&#xff1a;自然语言处理 主要业务问题&#xff1a; 随着互联网的日益发展&#xff0c;越来越多的人依赖网络搜索信息和分享交流。同时&#xff0c;股市投资者…

Java整合RabbitMQ实现生产消费(7种通讯方式)

文章目录环境说明工程搭建连接RabbitMQ通讯模式1.简单通讯2.工作队列通讯3.发布/订阅通讯4.路由通讯5.主题通讯6.RPC通讯7.Publisher确认通讯代码仓库环境说明 RabbitMQ环境&#xff0c;参考RabbitMQ环境搭建Java版本&#xff1a;JDK1.8Maven版本&#xff1a;apache-maven-3.6…

软件测试基础理论体系学习7-【一文看懂】什么是等价类划分法?边界值分析法?因果图法?错误推测法?功能图分析法?

7-【一文看懂】什么是等价类划分法&#xff1f;边界值分析法&#xff1f;因果图法&#xff1f;错误推测法&#xff1f;功能图分析法&#xff1f;1 等价类划分法1.1 理论知识1.1.1 划分等价类1.1.2 划分等价类的方法1.1.3 设计测试用例1.1.4 设计测试用例原则&#xff1a;1.2 等…

产品解读丨鸿翼ISO质量体系文件管理系统 合规 安全 高效

接轨国际&#xff0c;顺应全球标准化浪潮是当下国内制造企业发展过程的必经之路。通过建立从上而下的、符合国际各类标准的质量体系&#xff0c;鸿翼ISO质量体系文件管理系统能够严格监管企业质量体系的正常运转&#xff0c;为制造企业降本提效、重塑核心竞争力提供科学高效的解…

【JVM深层系列】「监控调优体系」针对于Alibaba-Arthas的安装入门及基础使用开发实战指南

Arthas特性介绍 Arthas是Alibaba开源的Java诊断工具&#xff0c;深受开发者喜爱。在线排查问题&#xff0c;无需重启&#xff1b;动态跟踪Java代码&#xff1b;实时监控JVM状态。 Arthas支持JDK 6&#xff0c;支持Linux/Mac/Windows&#xff0c;采用命令行交互模式&#xff0c…

网络电话会议摸鱼利器:会议自动退出器 - 网络会议结束后自动退出工具 方便会议挂机

随着远程办公和网络化的发展&#xff0c;我们可能经常需要开更多的在线电话会议。有些网络会议可能并不重要&#xff0c;但是你却不能一走了之。如果你打开了会议程序&#xff0c;然后埋头扎进Excel或笔记工具中&#xff0c;但没多一会一看&#xff0c;你竟然成了网络会议室中的…

叠氮聚乙二醇丙烯酰胺,N3-PEG-ACA,ACA-PEG-Azide

在铜催化剂催化下&#xff0c;叠氮可以与炔基在水溶液中发生click环化反应&#xff0c;生成含氮五元杂环。修饰性PEG广泛应用于修饰蛋白类药物、肽类化合物、有机小分子药物、生物材料等。 产品名称 叠氮聚乙二醇丙烯酰胺 N3-PEG-ACA 中文名称 叠氮PEG丙烯酰胺 丙烯酰胺P…

[附源码]Python计算机毕业设计SSM基于web动物园网站(程序+LW)

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

(附源码)php 网上投票系统 毕业设计 121500

基于PHP网上投票系统 摘 要 随着全球Internet的迅猛发展和计算机应用的普及&#xff0c;特别是近几年无线网络的广阔覆盖以及无线终端设备的爆炸式增长&#xff0c;使得人们能够随时随地的访问网络&#xff0c;以获取最新信息、参与网络活动、和他人在线互动。为了能及时地了解…

SpringMVC学习:一、概念、入门

SpringMVC 1.SpringMVC简介 ​ Spring Web MVC是一种基于Java的实现了Web MVC设计模式的请求驱动类型的轻量级Web 框架&#xff0c;即使用了MVC架构模式的思想&#xff0c;将web 层进行职责解耦&#xff0c;基于请求驱动指的就是使用请求-响应模型&#xff0c;框架的目的就是…

【C语言刷题】牛客网编程入门130题--精选题目(编程初学者赶紧进来!!!)

牛客编程入门130题–精选&#xff08;一&#xff09; 前言 以下题目来自牛客网的编程入门训练题库(<—)&#xff0c;题库适合大一&#xff0c;大二学生&#xff0c;题目有难有易&#xff0c;主要偏向入门。 不过里面还是有很多不错的题目&#xff0c;节约时间&#xff0c;没…

VM系列振弦采集模块 温度传感器使用及UART 通讯参数

VM系列振弦采集模块 温度传感器使用及UART 通讯参数 VMXXX 模块支持外接温度传感器&#xff0c;通过设置寄存器 TEMP_EX 的值来选择外接温度传感器的类型&#xff0c; 通过读取寄存器 TEMP 来获取实时的温度传感器测量值&#xff0c; 温度计算参数寄存器 TEMP_PAR1和 TEMP_PAR…

十一月券商金工精选

✦ 研报目录 ✦ ✦ 简述 ✦ 按发布时间排序 国信证券 财报中的竞争对手分析能否用来预测股票收益&#xff1f; 发布日期&#xff1a;2022-11-01 关键词&#xff1a;股票、文本分析、竞争对手 主要内容&#xff1a;竞争对手提及次数被定义为一家公司在全市场所有公司的最新…

VCS学习1

1、Verilog simulation event queue&#xff08;Verilog 仿真时间队列&#xff09; 龟腚&#xff1a; VCS大概的处理Verilog代码的流程&#xff1a; 上述流程在t0之前&#xff0c;先对一些不存在延时的一些语句进行处理&#xff0c;然后到达t0时刻&#xff0c;也称为current t…

web网页制作与实现 html+css+javascript+jquery+bootstarp响应式美食网站设计与实现

&#x1f380; 精彩专栏推荐&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb; ✍️ 作者简介: 一个热爱把逻辑思维转变为代码的技术博主 &#x1f482; 作者主页: 【主页——&#x1f680;获取更多优质源码】 &#x1f393; web前端期末大作业…

算法竞赛入门【码蹄集进阶塔335题】(MT2001-2025)

算法竞赛入门【码蹄集进阶塔335题】(MT2001-2025&#xff09; 文章目录算法竞赛入门【码蹄集进阶塔335题】(MT2001-2025&#xff09;前言为什么突然想学算法了&#xff1f;为什么选择码蹄集作为刷题软件&#xff1f;目录1. MT2001 幸运的32. MT2002 买马3. MT2003 三角数4. MT2…