求解迷宫最短路径

1. 多通路迷宫初始化

    先构建一个多通路迷宫,并且对其初始化

void MazeInitShortPath(Maze* maze)
{if(maze == NULL){return;}int row = 0;int col = 0;for(; row < MAX_COL; row++){for(col = 0; col < MAX_COL; col++){maze -> map[row][col] = Map[row][col];}printf("\n");}
}

                        这里写图片描述

2. 定义一个栈并且打印

/** * @brief* * @用来测试迷宫栈* @param msg       */
void SeqStackDebugPrint(SeqStack* short_path, char* msg)
{printf("[%s]\n", msg);if(short_path == NULL || msg == NULL){return;}int i =0;for(;i < short_path -> size; i++){printf("(%d, %d)\n", short_path -> data[i].row, short_path -> data[i].col);}printf("\n");
}
3. 递归找通路

    在次过程中, 用到的思路和上一篇的迷宫求通路的思路一样. 即就是利用递归的方式实现.不过因为此次有好多个出口, 所以我们每次都需要定义两个栈, 保存当前路径, 以及最短路径, 最后将最短路径中的内容打印出来.首先, 先判断当前点是否可以落脚, 如果不能落脚, 就直接退出, 如果可以落脚, 就现将当前位置标记, 然后将其入栈, 再判断当前位置是否是出口, 如果是出口就得判断当前栈和最短路径栈中它们两个哪个路径短, 如果当前路径比最短路径的步数少, 或者最短;路径栈为空, 就用当前栈代替保存最短路径的那个栈, 同时需要进行回溯, 将保存当前路径的栈出栈.如果当前位置不是出口, 就对当前位置周围的四个位置进行探索,直到找到出口为止. 如果当前位置周围的四个点都已经探索, 此时就需要回溯了, 回溯的过程中也需要将保存当前位置的栈的元素出栈.

//辅助递归
void _GetShortPath(Maze* maze, Point cur, Point entry, SeqStack* cur_path, SeqStack* short_path)
{if(maze == NULL){return;}printf("(%d, %d)\n", cur.row, cur.col);//1. 判断当前是否可以落脚if(CanStay(maze, cur) == 0){return;}//2. 能落脚就将其标记, 插入到cur_pathMark(maze, cur);SeqStackPush(cur_path, cur);//3. 判定当前是否是出口//b) 如果当前路径没有short_path短, 就回溯找其他路径, 在回溯前也需要将 cur_path 出栈if(IsExit(maze, cur, entry)){printf("找到了一条较短的路\n");if(cur_path -> size < short_path -> size || short_path -> size == 0){//a) 如果是出口, 说明找到了一条路, 拿着当路径和short_path 比较, 如果当前路径比 short_path 路径短, //应当前路径代替 short_path(打擂台), 或者 short_path 是个空栈, 就用当前栈代替short_path, 代替完//需要回溯, 找其他路径SeqStackAssgin(short_path, cur_path);}SeqStackPop(cur_path);return;}//4. 当前点不是出口, 尝试找四个方向(探测四个方向)Point up = cur;up.row -= 1;_GetShortPath(maze, up, entry, cur_path, short_path);Point right = cur;right.col += 1;_GetShortPath(maze, right, entry, cur_path, short_path);Point down = cur;down.row += 1;_GetShortPath(maze, down, entry, cur_path, short_path);Point left = cur;left.col -= 1;_GetShortPath(maze, left, entry, cur_path, short_path);//5. 如果四个方向都探测过了, 回溯返回到上一个点, 同时 cur_path 出栈 SeqStackPop(cur_path);
}
void GetShortPath(Maze* maze, Point entry)
{if(maze == NULL){return;}if(entry.row < 0 || entry.row >= MAX_ROW || entry.col < 0 || entry.col >= MAX_COL){return;}SeqStack cur_path;SeqStack short_path;SeqStackInit(&cur_path);SeqStackInit(&short_path);_GetShortPath(maze, entry, entry, &cur_path, &short_path);SeqStackDebugPrint(&short_path, "打印栈内容");printf("%d\n", short_path.size);
}
4. 栈的复制

    为了代码实现的简单, 我们定义两个栈, from, to, from比to的元素要少. 在复制之前, 将to 的内存先进行释放, 然后对to进行动态内存分配, 接着将 from 结构体的所有信息全部复制到 to 中,最后将from中的元素依次复制给 to即可

void SeqStackAssgin(SeqStack* to, SeqStack* from)
{if(from == NULL || to == NULL){return;}SeqStackDestroy(to);to -> data = (Point*)malloc(from -> capacity * sizeof(SeqStackType));to -> size = from -> size;int i = 0;for(; i < from -> size; i++){to -> data[i] = from -> data[i];}
}

                        这里写图片描述
                        这里写图片描述

5. 总结

    总结一下, 整体思路如下. 先定义两个栈 cur_path , shrott_path, 前者保存当前路径.后者保存最短路径, 接着 判断当前位置是否可以落脚, 如果不能落脚就直接返回, 如果可以落脚就将当前位置标记, 然后将当前点进行入栈, 入栈到 cur_path中, 接下来判断当前位置是否为出口, 如果是出口, 就比较 cur_path 和 short_path 之间的长度, 如果 cur_path的元素少于 short_path 的元素或者 short_path 为空, 就用cur_path 代替 short_path, 然后将当前 cur_path 栈出栈, 接着进行回溯. 如果当前栈的元素个数大于 short_path栈的元素, 就将 cur_path 出栈, 然后进行回溯; 如果当前位置不是出口, 就按照顺序(顺时针)探测当前位置周围的四个点, 如果当前位置周围的四个点都已经探测, 此时说明进入了死胡同, 就需要回溯, 回溯之前不要忘记将当前的栈 cur_path 进行出栈, 最后,当递归结束时, 打印 short_path栈, 因为该栈里保存的就是最短路径

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

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

相关文章

带环迷宫求最短路径

前面介绍了简单的迷宫求解问题, 今天我们就对带环迷宫求出它的最短路径 1.首先来看一个带环迷宫的简单地图 在这张迷宫地图中,我们规定入口点的位置entry的坐标是 (0, 1), 同时, 我们给入口点传一个非法坐标,作为入口点的前一个位置(-1, -1). 接下来的思路就和上一篇的思路是一…

线程的同步与互斥

1. 互斥量 在Linux 下线程使用的都是局部变量, 而我们知道, 每一个线程都独立拥有自己的一个栈, 而这些局部便令就在栈中,而线程的创建就是为了实现通信, 此时线程之间无法共享这些变量     为了使得线程之间能够共享数据, 一次我们可以创建一个全局变量, 此时线程都在进程…

C语言 可变参数

http://www.cnblogs.com/zhanggaofeng/p/6434554.html //可变参数 #include <stdio.h> #include <stdlib.h> #include <string.h> //引用头文件 #include <stdarg.h>/* va_list用于声明一个变量&#xff0c;我们知道函数的可变参数列表其实就是一个字符…

c语言经典算法——查找一个整数数组中第二大数

https://www.cnblogs.com/dootoo/p/4473958.html 题目&#xff1a; 实现一个函数&#xff0c;查找一个整数数组中第二大数。 算法思想&#xff1a; 设置两个变量max1和max2&#xff0c;用来保存最大数和第二大数&#xff0c;然后将数组剩余的数依次与这两个数比较&#xff0c;如…

进程间关系和守护进程

一. 进程组/作业/会话 1.进程组 每一个进程除了有一个进程ID之外, 还属于一个进程组. 进程是一个或多个进程的集合. 通常, 它们与同一个作业向关联, 可以接收来自同一个终端下的各种命令,信号. 每一个进程组都有唯一的进程组 ID. 每一个进程组都可以有一个组长进程. 组长进程的…

猴子偷桃问题

http://blog.csdn.net/snow_5288/article/details/52561882 问题描述&#xff1a; /*有一群猴子&#xff0c;去摘了一堆桃子*/ /*商量之后决定每天吃剩余桃子的一半*/ /*当每天大家吃完桃子之后&#xff0c;有个贪心的小猴都会偷偷再吃一个桃子*/ /*按照这样的方式猴子们每天都…

网络相关基础概念

一. 相关基础概念 1.计算机网络的特点 (1)连通性:计算机网络使得上网的用户都能够彼此相连, 好像用户的计算机可以直接相连     (2)资源共享:资源共享可以是信息共享, 软件共享, 硬件共享等等. 由于网络的存在, 使得用户感觉资源就在自己身边 2. 网络 网络是由若干结点和…

linux线程同步(2)-条件变量

https://www.cnblogs.com/yuuyuu/p/5140875.html linux线程同步(2)-条件变量 一.概述 上一篇&#xff0c;介绍了互斥量。条件变量与互斥量不同&#xff0c;互斥量是防止多线程同时访问共享的互斥变量来保护临界区。条件变量…

点对点数据链路层

数据链路层的主要功能将数据转换为相应的比特流使用的信道主要有点对点的信道方式(一对一的方式), 以及广播的信道方式 一. 点对点信道的数据链路层 1. 数据链路和数据帧 链路就是从一个结点连接到相邻结点的一段物理线路(有线或者无线), 期间不准有任何的交换结点, 因此两台…

linux线程同步(1)-互斥量

http://www.cnblogs.com/yuuyuu/p/5140251.html 一.概述 互斥量是线程同步的一种机制&#xff0c;用来保护多线程的共享资源。同一时刻&#xff0c;只允许一个线程对临界区进行访问。 互斥量的工作流程&#xff1a;创建一个…

linux线程同步(3)-读写锁

http://www.cnblogs.com/yuuyuu/p/5143881.html 一.概述 读写锁与互斥量的功能类似&#xff0c;对临界区的共享资源进行保护&#xff01;互斥量一次只让一个线程进入临界区&#xff0c;读写锁比它有更高的并行性。读写锁有…

linux线程同步(5)-屏障

http://www.cnblogs.com/yuuyuu/p/5152560.html 一.概述 barrier(屏障)与互斥量&#xff0c;读写锁&#xff0c;自旋锁不同&#xff0c;它不是用来保护临界区的。相反&#xff0c;它跟条件变量一样&#xff0c;是用来协同多…

Linux多线程与同步

https://www.cnblogs.com/freedomabcd/p/7774743.html 典型的UNIX系统都支持一个进程创建多个线程(thread)。在Linux进程基础中提到&#xff0c;Linux以进程为单位组织操作&#xff0c;Linux中的线程也都基于进程。尽管实现方式有异于其它的UNIX系统&#xff0c;但Linux的多线程…

内存管理(二)

页面置换算法 当发生缺页中断的时候, 系统会在内存中选择一个页面将其换出内存, 而当换出内存的时候如果该页面的内容在内存中发生修改,则必须将该新数据重新写回到磁盘, 然后再将需要换进的数据覆盖掉原来的数据, 而当该数据在内存中没有被修改的时候, 此时就直接用需要换进的…

数据链路层:基本概念

数据链路层的定义 对数据链路层有对上的网络层接口. 对下提供物理层的接口. 定义合适的传输差错率 对传输流进行管理, 以免快速的传输的数据被淹没. 比如发送端发送信号太快, 接受方接受速度较慢, 此时数据链路层就需要提供一定的功能解决这个问题 物理层上传输的基本单元是…

数据链路层: 可靠性传输 六个协议

可靠性传输 1. 差错控制 发送方将数据帧发送, 但是当发送方发送的是一个 1的时候此时接受方却接受的是一个 0. (1)校验 接收方如果帧校验接受到的帧没有问题, 则对发送方发送一个肯定性的确认, 当对这个数据帧进行校验发现这个帧有问题的时候, 此时接受方一种是将这个数据帧…

c语言实现配置文件的读写

配置文件的格式如下&#xff1a; key1 value1 key2 value2 . . . 名值对以一个链接&#xff0c;一条记录以换行符分割 头文件&#xff1a; #include<stdio.h> #include<stdlib.h> #include <string.h> 函数原型&#xff1a; void trim(char *strIn, char *…

数据链路层: HDLC

一. 协议机 发送方和接收方. 同时有限状态机把协议形式化为一个四元组 (S,M,I,T), 其中你S表示进程和信道可能进入的集合, M 表示数据帧的状态, I 表示进程的初始状态, T 表示两两状态之间的转化. 每个系统状态可以分为发送状态, 接受状态和信道状态. 把状态用一个点进行表示,…

bob-tong 字符串函数之Strtok()函数

https://www.cnblogs.com/Bob-tong/p/6610806.html Strtok()函数详解&#xff1a; 该函数包含在"string.h"头文件中 函数原型&#xff1a; char* strtok (char* str,constchar* delimiters ); 函数功能&#xff1a;   切割字符串&#xff0c;将str切分成一个个子…

数据链路层:SLIP(串型线路IP) PPP(点对点协议)

SLIP 没有差错控制, 传输时必须知道对方IP, 传输使用于低速业务 19.2k.应用非常受限 PPP协议 1. PPP协议功能 处理错误检测 支持多协议(IP, IPX, DECnet 等) 连接时允许协商 IP 地址 允许身份验证 2. PPP 的组成 串型链路上封装数据报, 即支持异步链路也支持面向 比特…