草庐IT

数据结构与算法——深度寻路算法

热爱编程的小K 2023-04-14 原文

📖作者介绍:22级树莓人(计算机专业),热爱编程<目前在c++阶段,因为最近参加新星计划算法赛道(白佬),所以加快了脚步,果然急迫感会增加动力>——目标Windows,MySQL,Qt,数据结构与算法,Linux,多线程,会持续分享学习成果和小项目的
📖作者主页:king&南星
📖专栏链接:数据结构

🎉欢迎各位→点赞👏 + 收藏💞 + 留言🔔​
💬总结:希望你看完之后,能对你有所帮助,不足请指正!共同学习交流 🐾

文章目录


🤖1、介绍

深度寻路算法:使用的是栈模板,通过将其走过的点的坐标压入栈中,然后遍历其所在位置的各个方向寻找可以通行的"路径",一般情况下当迷宫的范围不太大时,其又存在路径是可以遍历到路径的,但是深度寻路并不会寻找最短路径。 并且 当迷宫足够大时,且其可通行的点足够多时,也就是一直都有点压入栈中,这时是找不到迷宫的出口的,还会使栈的占用内存过大,导致栈溢出。 深度优先搜索的规则是沿着一个固定的方向进行行走,等到了一个岔路口再继续选择方向,如果碰上了死胡同再退回下一个岔路口重新选择方向。 走过的路不会重新走,一次只走一个岔路口。深度寻路只能走直线 不能走斜线

👾2、地图的描绘

用二维数组来描述,可以用其他数据结构来描述 图结构

//地图  1表示障碍 0表示路
	int map[ROWS][COLS] = {
		{ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
		{ 1, 0, 1, 1, 0, 0, 0, 1, 1, 1 },
		{ 1, 0, 1, 1, 0, 1, 0, 0, 0, 1 },
		{ 1, 0, 1, 1, 0, 1, 0, 1, 0, 1 },
		{ 1, 0, 1, 1, 0, 1, 0, 1, 0, 1 },
		{ 1, 0, 0, 0, 0, 1, 0, 1, 0, 1 },
		{ 1, 0, 1, 1, 1, 1, 0, 1, 0, 1 },
		{ 1, 0, 1, 1, 1, 1, 0, 1, 0, 1 },
		{ 1, 0, 1, 1, 1, 1, 0, 1, 0, 1 },
		{ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
	};

👻3、试探方向

试探 一般是顺时针或者逆时针
好马不吃回头草
人为规定试探方向顺序并且一开始所有的点都是一样
例如:一开始每个点都是 上
试探顺序是 上 左 下 右 逆时针
已经走过的应当标记,试探的时候走过的不走

所以我在这里准备了预测点和辅助地图,预测点的作用是探测是墙还是路,能不能走;辅助地图的作用是标记已经走过的地方和方向

	//点
	Mypoint begPos = { 1,1 };
	Mypoint endPos = { 8,8 };
	//辅助地图,标记起点走过
	pathMap PathMap[ROWS][COLS] = { 0 };
	PathMap[begPos.row][begPos.row].isFind = true;
	//栈 起点入栈
	Stack stack;
	init(&stack);
	push(&stack, &begPos);

	//标记没有找到终点
	bool isFindEnd = false;
	//当前点
	Mypoint currentPos;
	currentPos.row = begPos.row;
	currentPos.col = begPos.col;
	//预测点
	Mypoint searchPos;

🤡4、死胡同问题

回退机制
栈结构:先入后出,后入先出
1 走过就入栈
2 遇到死胡同(每个方向都试过还不能走 最后一个方向右都不能走)回退
2.1 pop 出栈一个
2.2 跳到当前栈顶元素处

例如下图,当走到8,1的时候遇到死胡同,这里只需要把栈顶元素删掉,然后跳到当前栈顶元素

😼5、Stack代码

.h文件

#ifndef _MY_STACK_H_
#define _MY_STACK_H_
#include"Mytypes.h"
#include<string.h>
#include<stdlib.h>
typedef struct Stack 
{
	Mypoint* pArr;     //记录内存首地址
	int size;          //记录当前元素个数
	int capacity;      //记录当前容量
}Stack;
//初始化
void init(Stack* S);
//添加元素
void push(Stack* S, Mypoint* pos);
//删除元素
void pop(Stack* S);
//获取栈顶元素
Mypoint* getTop(Stack* S);
//判断栈是否为空
bool isEmpty(Stack* S);
#endif // !_MY_STACK_H_

.c文件

#include "MyStack.h"
#include<assert.h>
void init(Stack* S)
{
    S->size = S->capacity = 0;
    S->pArr = NULL;
}

void push(Stack* S, Mypoint* pos)
{
    if ( S->size >= S->capacity )
    {
        S->capacity += (((S->capacity >> 1) > 1) ? (S->capacity >> 1) : 1);
        Mypoint* king = malloc(sizeof(Mypoint) * (S->capacity));
        assert(king);
        if ( S->pArr )
        {
            memcpy(king, S->pArr, sizeof(Mypoint) * (S->size));
            free(S->pArr);
        }
        S->pArr = king;
    }
    S->pArr[S->size].row = pos->row;
    S->pArr[S->size].col = pos->col;
    S->size++;
}

void pop(Stack* S)
{
    S->size--;
}

Mypoint* getTop(Stack* S)
{
    return (S->pArr + (S->size - 1));
}

bool isEmpty(Stack* S)
{
    return (S->size == 0);
}

💝6、算法代码

.h文件

#ifndef _MY_TYPES_H_
#define _MY_TYPES_H_
#include<stdio.h>
#include<stdbool.h>
#define ROWS 10
#define COLS 10

//地图区分
enum type { road, wall };

//方向类型,上左下右
enum direct { p_up, p_left, p_down, p_right };

//定义点类型
typedef struct Mypoint
{
	int row, col;
}Mypoint;

//辅助地图类
typedef struct pathMap 
{
	int dir;			//记录当前方向
	bool isFind;		//是否走过 false没走过 true走过
}pathMap;

#endif

.c文件

#include"Mytypes.h"
#include"MyStack.h"
#include<windows.h>
void drawMap(int map[ROWS][COLS],Mypoint* p) 
{
	Sleep(300);
	system("cls");
	for (int i = 0; i < ROWS; i++) 
	{
		for (int j = 0; j < COLS; j++) 
		{
			if (p->row == i && p->col == j) 
			{
				printf("人");
			}
			else if (wall == map[i][j]) 
			{
				printf("墙");
			}
			else 
			{
				printf("  ");
			}
		}
		printf("\n");
	}
}
int main()
{
	//地图  1表示障碍 0表示路
	int map[ROWS][COLS] = {
		{ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
		{ 1, 0, 1, 1, 0, 0, 0, 1, 1, 1 },
		{ 1, 0, 1, 1, 0, 1, 0, 0, 0, 1 },
		{ 1, 0, 1, 1, 0, 1, 0, 1, 0, 1 },
		{ 1, 0, 1, 1, 0, 1, 0, 1, 0, 1 },
		{ 1, 0, 0, 0, 0, 1, 0, 1, 0, 1 },
		{ 1, 0, 1, 1, 1, 1, 0, 1, 0, 1 },
		{ 1, 0, 1, 1, 1, 1, 0, 1, 0, 1 },
		{ 1, 0, 1, 1, 1, 1, 0, 1, 0, 1 },
		{ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
	};
	//点
	Mypoint begPos = { 1,1 };
	Mypoint endPos = { 8,8 };
	//辅助地图,标记起点走过
	pathMap PathMap[ROWS][COLS] = { 0 };
	PathMap[begPos.row][begPos.row].isFind = true;
	//栈 起点入栈
	Stack stack;
	init(&stack);
	push(&stack, &begPos);

	//标记没有找到终点
	bool isFindEnd = false;
	//当前点
	Mypoint currentPos;
	currentPos.row = begPos.row;
	currentPos.col = begPos.col;
	//预测点
	Mypoint searchPos;

	//寻路
	while (1)
	{
		//找到试探点
		searchPos.row = currentPos.row;
		searchPos.col = currentPos.col;
		//根据当前点的试探方向,确定试探点
		switch (PathMap[currentPos.row][currentPos.col].dir)
		{
			case p_up:
				searchPos.row--;
				//试探方向改变
				PathMap[currentPos.row][currentPos.col].dir = p_left;
				//判断能不能走
				if ( road == map[searchPos.row][searchPos.col] &&
					PathMap[searchPos.row][searchPos.col].isFind == false )
				{
					//走
					currentPos.row = searchPos.row;
					currentPos.col = searchPos.col;
					//记录走过
					PathMap[currentPos.row][currentPos.col].isFind = true;
					//入栈
					push(&stack, &currentPos);
				}
				break;
			case p_left:
				searchPos.col--;
				//试探方向改变
				PathMap[currentPos.row][currentPos.col].dir = p_down;
				//判断能不能走
				if (road == map[searchPos.row][searchPos.col] &&
					PathMap[searchPos.row][searchPos.col].isFind == false)
				{
					//走
					currentPos.row = searchPos.row;
					currentPos.col = searchPos.col;
					//记录走过
					PathMap[currentPos.row][currentPos.col].isFind = true;
					//入栈
					push(&stack, &currentPos);
				}
				break;
			case p_down:
				searchPos.row++;
				//试探方向改变
				PathMap[currentPos.row][currentPos.col].dir = p_right;
				//判断能不能走
				if (road == map[searchPos.row][searchPos.col] &&
					PathMap[searchPos.row][searchPos.col].isFind == false)
				{
					//走
					currentPos.row = searchPos.row;
					currentPos.col = searchPos.col;
					//记录走过
					PathMap[currentPos.row][currentPos.col].isFind = true;
					//入栈
					push(&stack, &currentPos);
				}
				break;
			case p_right:
				searchPos.col++;
				//判断能不能走
				if (road == map[searchPos.row][searchPos.col] &&
					PathMap[searchPos.row][searchPos.col].isFind == false)
				{
					//走
					currentPos.row = searchPos.row;
					currentPos.col = searchPos.col;
					//记录走过
					PathMap[currentPos.row][currentPos.col].isFind = true;
					//入栈
					push(&stack, &currentPos);
				}
				else
				{
					//出栈
					pop(&stack);
					//跳到当前栈顶元素处
					currentPos.row = getTop(&stack)->row;
					currentPos.col = getTop(&stack)->col;
				}
				break;
		}
		drawMap(map, &currentPos);
		//是否找到终点了
		if ( currentPos.col == endPos.col && currentPos.row == endPos.col )
		{
			isFindEnd = true;
			break;
		}
		//退回去了 栈空
		if (isEmpty(&stack)) break;
	}
	if ( isFindEnd )
	{
		printf("找到终点了:\n");
		while ( !isEmpty(&stack ))
		{
			printf("(%d,%d)", getTop(&stack)->row, getTop(&stack)->col);
			pop(&stack);
		}
		printf("\n");
	}
	return 0;
}

有关数据结构与算法——深度寻路算法的更多相关文章

  1. ruby - 使用 ruby​​ 将 HTML 转换为纯文本并维护结构/格式 - 2

    我想将html转换为纯文本。不过,我不想只删除标签,我想智能地保留尽可能多的格式。为插入换行符标签,检测段落并格式化它们等。输入非常简单,通常是格式良好的html(不是整个文档,只是一堆内容,通常没有anchor或图像)。我可以将几个正则表达式放在一起,让我达到80%,但我认为可能有一些现有的解决方案更智能。 最佳答案 首先,不要尝试为此使用正则表达式。很有可能你会想出一个脆弱/脆弱的解决方案,它会随着HTML的变化而崩溃,或者很难管理和维护。您可以使用Nokogiri快速解析HTML并提取文本:require'nokogiri'h

  2. ruby - 解析 RDFa、微数据等的最佳方式是什么,使用统一的模式/词汇(例如 schema.org)存储和显示信息 - 2

    我主要使用Ruby来执行此操作,但到目前为止我的攻击计划如下:使用gemsrdf、rdf-rdfa和rdf-microdata或mida来解析给定任何URI的数据。我认为最好映射到像schema.org这样的统一模式,例如使用这个yaml文件,它试图描述数据词汇表和opengraph到schema.org之间的转换:#SchemaXtoschema.orgconversion#data-vocabularyDV:name:namestreet-address:streetAddressregion:addressRegionlocality:addressLocalityphoto:i

  3. ruby - Ruby 有 `Pair` 数据类型吗? - 2

    有时我需要处理键/值数据。我不喜欢使用数组,因为它们在大小上没有限制(很容易不小心添加超过2个项目,而且您最终需要稍后验证大小)。此外,0和1的索引变成了魔数(MagicNumber),并且在传达含义方面做得很差(“当我说0时,我的意思是head...”)。散列也不合适,因为可能会不小心添加额外的条目。我写了下面的类来解决这个问题:classPairattr_accessor:head,:taildefinitialize(h,t)@head,@tail=h,tendend它工作得很好并且解决了问题,但我很想知道:Ruby标准库是否已经带有这样一个类? 最佳

  4. ruby - 是否有用于序列化和反序列化各种格式的对象层次结构的模式? - 2

    给定一个复杂的对象层次结构,幸运的是它不包含循环引用,我如何实现支持各种格式的序列化?我不是来讨论实际实现的。相反,我正在寻找可能会派上用场的设计模式提示。更准确地说:我正在使用Ruby,我想解析XML和JSON数据以构建复杂的对象层次结构。此外,应该可以将该层次结构序列化为JSON、XML和可能的HTML。我可以为此使用Builder模式吗?在任何提到的情况下,我都有某种结构化数据-无论是在内存中还是文本中-我想用它来构建其他东西。我认为将序列化逻辑与实际业务逻辑分开会很好,这样我以后就可以轻松支持多种XML格式。 最佳答案 我最

  5. ruby - 我如何添加二进制数据来遏制 POST - 2

    我正在尝试使用Curbgem执行以下POST以解析云curl-XPOST\-H"X-Parse-Application-Id:PARSE_APP_ID"\-H"X-Parse-REST-API-Key:PARSE_API_KEY"\-H"Content-Type:image/jpeg"\--data-binary'@myPicture.jpg'\https://api.parse.com/1/files/pic.jpg用这个:curl=Curl::Easy.new("https://api.parse.com/1/files/lion.jpg")curl.multipart_form_

  6. 世界前沿3D开发引擎HOOPS全面讲解——集3D数据读取、3D图形渲染、3D数据发布于一体的全新3D应用开发工具 - 2

    无论您是想搭建桌面端、WEB端或者移动端APP应用,HOOPSPlatform组件都可以为您提供弹性的3D集成架构,同时,由工业领域3D技术专家组成的HOOPS技术团队也能为您提供技术支持服务。如果您的客户期望有一种在多个平台(桌面/WEB/APP,而且某些客户端是“瘦”客户端)快速、方便地将数据接入到3D应用系统的解决方案,并且当访问数据时,在各个平台上的性能和用户体验保持一致,HOOPSPlatform将帮助您完成。利用HOOPSPlatform,您可以开发在任何环境下的3D基础应用架构。HOOPSPlatform可以帮您打造3D创新型产品,HOOPSSDK包含的技术有:快速且准确的CAD

  7. 区块链之加解密算法&数字证书 - 2

    目录一.加解密算法数字签名对称加密DES(DataEncryptionStandard)3DES(TripleDES)AES(AdvancedEncryptionStandard)RSA加密法DSA(DigitalSignatureAlgorithm)ECC(EllipticCurvesCryptography)非对称加密签名与加密过程非对称加密的应用对称加密与非对称加密的结合二.数字证书图解一.加解密算法加密简单而言就是通过一种算法将明文信息转换成密文信息,信息的的接收方能够通过密钥对密文信息进行解密获得明文信息的过程。根据加解密的密钥是否相同,算法可以分为对称加密、非对称加密、对称加密和非

  8. FOHEART H1数据手套驱动Optitrack光学动捕双手运动(Unity3D) - 2

    本教程将在Unity3D中混合Optitrack与数据手套的数据流,在人体运动的基础上,添加双手手指部分的运动。双手手背的角度仍由Optitrack提供,数据手套提供双手手指的角度。 01  客户端软件分别安装MotiveBody与MotionVenus并校准人体与数据手套。MotiveBodyMotionVenus数据手套使用、校准流程参照:https://gitee.com/foheart_1/foheart-h1-data-summary.git02  数据转发打开MotiveBody软件的Streaming,开始向Unity3D广播数据;MotionVenus中设置->选项选择Unit

  9. 使用canal同步MySQL数据到ES - 2

    文章目录一、概述简介原理模块二、配置Mysql使用版本环境要求1.操作系统2.mysql要求三、配置canal-server离线下载在线下载上传解压修改配置单机配置集群配置分库分表配置1.修改全局配置2.实例配置垂直分库水平分库3.修改group-instance.xml4.启动监听四、配置canal-adapter1修改启动配置2配置映射文件3启动ES数据同步查询所有订阅同步数据同步开关启动4.验证五、配置canal-admin一、概述简介canal是Alibaba旗下的一款开源项目,Java开发。基于数据库增量日志解析,提供增量数据订阅&消费。Git地址:https://github.co

  10. ruby-on-rails - 创建 ruby​​ 数据库时惰性符号绑定(bind)失败 - 2

    我正在尝试在Rails上安装ruby​​,到目前为止一切都已安装,但是当我尝试使用rakedb:create创建数据库时,我收到一个奇怪的错误:dyld:lazysymbolbindingfailed:Symbolnotfound:_mysql_get_client_infoReferencedfrom:/Library/Ruby/Gems/1.8/gems/mysql2-0.3.11/lib/mysql2/mysql2.bundleExpectedin:flatnamespacedyld:Symbolnotfound:_mysql_get_client_infoReferencedf

随机推荐