带环迷宫求最短路径

前面介绍了简单的迷宫求解问题, 今天我们就对带环迷宫求出它的最短路径
1.首先来看一个带环迷宫的简单地图

                                这里写图片描述
    在这张迷宫地图中,我们规定入口点的位置entry的坐标是 (0, 1), 同时, 我们给入口点传一个非法坐标,作为入口点的前一个位置(-1, -1). 接下来的思路就和上一篇的思路是一样的的了. 即每次判断当前点是否可以落脚, 如果不能落脚就直接退出, 如果可以落脚, 就将当前位置的点进行入栈操作, 将其标记(和前面不一样了), 接着判断当前点是否是出口, 如果是出口, 就将拿着 cur_path 和 short_path 进行比较, 将较短的保存在 short_path 中, 然后将 cur_path 出栈, 接着再进行回溯. 如果当前点不是出口, 就按照顺序依次探测当前点周围的四个点, 如果四个点都已经探测完了, 就需要回溯, 回溯的同时不要忘记将当前栈 cur_path 出栈

2. 判断当前位置是否可以落脚

    判断当前位置是否可以落脚可以分为以下两种情况
    (1)当前位置还没有走过
    此时地图对应的二维数组的值是 1, 即这个位置一定可以落脚
    (2)当前位置如果已经走过, 我们需要借助当前位置的前一个落脚元素来判断当前位置是否可以落脚, 当前一个位置在地图上对应的值加1 小于当前位置在地图上的值的时候, 此时证明该位置就可以落脚, 即 cur > pre + 1此时就可以落脚

int CanStayWithCircle(Maze* maze, Point cur, Point prev)
{if(maze == NULL){return 0;}if(cur.row < 0 || cur.row >= MAX_ROW || cur.col < 0 || cur.col >= MAX_COL){return 0;}//当前位置是墙if(maze -> map[cur.row][cur.col] == 0){return 0;}//在取 prev 之前判断 prev 是否合法if(prev.row == -1 && prev.col == -1){return 1;}//此时的prev 已经不再是入口点的前一个坐标if(prev.row < 0 || prev.row >= MAX_ROW || prev.col < 0 || prev.col >= MAX_COL){return 0;}//当前位置已经走过, 比较 cur 和 prev 的大小关系if(maze -> map[cur.row][cur.col] > maze -> map[prev.row][prev.col] + 1){return 1;}//如果当前点是 1 就直接可以落脚if(maze -> map[cur.row][cur.col] == 1){return 1;}return 0;
}
3. 对当前位置进行标记

    对当前位置标记分为两种情况, 第一种就是看当前位置是否为入口, 如果是入口, 就将地图对应的当前位置处的坐标变为2,否则就是让 map[cur.row][cur.col] = map[prev.row][prev.col] + 1

void MarkShortPathWithCircle(Maze* maze, Point cur, Point prev)
{if(maze == NULL){return;}if(cur.row < 0 || cur.row >= MAX_ROW || cur.col < 0 || cur.col >= MAX_COL){return;}if(prev.row < -1 || prev.row >= MAX_ROW || prev.col < -1 || prev.col >= MAX_COL){return;}if(prev.row == -1 && prev.col == -1){maze -> map[cur.row][cur.col] = 2;return;}maze -> map[cur.row][cur.col] = maze -> map[prev.row][prev.col] + 1;return;
}
3. 迷宫求解递归代码
int CanStayWithCircle(Maze* maze, Point cur, Point prev)
{if(maze == NULL){return 0;}if(cur.row < 0 || cur.row >= MAX_ROW || cur.col < 0 || cur.col >= MAX_COL){return 0;}//当前位置是墙if(maze -> map[cur.row][cur.col] == 0){return 0;}//在取 prev 之前判断 prev 是否合法if(prev.row == -1 && prev.col == -1){return 1;}//此时的prev 已经不再是入口点的前一个坐标if(prev.row < 0 || prev.row >= MAX_ROW || prev.col < 0 || prev.col >= MAX_COL){return 0;}//当前位置已经走过, 比较 cur 和 prev 的大小关系if(maze -> map[cur.row][cur.col] > maze -> map[prev.row][prev.col] + 1){return 1;}//如果当前点是 1 就直接可以落脚if(maze -> map[cur.row][cur.col] == 1){return 1;}return 0;
}void MarkShortPathWithCircle(Maze* maze, Point cur, Point prev)
{if(maze == NULL){return;}if(cur.row < 0 || cur.row >= MAX_ROW || cur.col < 0 || cur.col >= MAX_COL){return;}if(prev.row < -1 || prev.row >= MAX_ROW || prev.col < -1 || prev.col >= MAX_COL){return;}if(prev.row == -1 && prev.col == -1){maze -> map[cur.row][cur.col] = 2;return;}maze -> map[cur.row][cur.col] = maze -> map[prev.row][prev.col] + 1;return;
}void _GetShortPathWithCircle(Maze* maze, Point entry, Point cur, SeqStack* cur_path, SeqStack* short_path, Point prev)
{if(maze == NULL){return;}if(entry.row < 0 || entry.row >= MAX_ROW || entry.col < 0 || entry.col >= MAX_COL){return;}if(cur.row < 0 || cur.row >= MAX_ROW || cur.col < 0 || cur.col >= MAX_COL){return;}if(cur_path == NULL || short_path == NULL){return;}//1. 判定当前点是否可以落脚if(CanStayWithCircle(maze, cur, prev) == 0){return;}//2. 如果能落脚, 就标记当前点, 并将其入栈到 cur_path中MarkShortPathWithCircle(maze, cur, prev);SeqStackPush(cur_path, cur);//3. 判定当前是否是出口if(IsExit(maze, cur, entry))// a) 如果是出口, 就将 cur_path 和 short_path 比较, 把较短的路径保存到 cur_path 中// 还有一种就是如果 short_path 的长度为 0, 就用 cur_path 代替 short_path ,然后将 cur_path// 出栈, 并且回溯{printf("找到了一条路\n");if(cur_path -> size < short_path -> size || short_path -> size == 0){SeqStackAssgin(short_path, cur_path);}SeqStackPop(cur_path);return;}// b) 如果不是出口, 以当前点为基准, 顺时针探测 周围四个点Point up = cur;up.row -= 1;_GetShortPathWithCircle(maze, entry, up, cur_path, short_path, cur);Point right = cur;right.col += 1;_GetShortPathWithCircle(maze, entry, right, cur_path, short_path, cur);Point down = cur;down.row += 1;_GetShortPathWithCircle(maze, entry, down, cur_path, short_path, cur);Point left = cur;left.col -= 1;_GetShortPathWithCircle(maze, entry, left, cur_path, short_path, cur);//4. 如果四个方向都探测过了, 回溯SeqStackPop(cur_path);return;
}void GetShortPathWithCircle(Maze* maze, Point entry, Point prev)
{if(maze == NULL){return;//非法输入}if(entry.row < 0 || entry.row >= MAX_ROW || entry.col < 0 || entry.col >= MAX_COL){return;//非法输入}//规定第一个prev点的坐标是(-1, -1)if(prev.row != -1 && prev.col != -1){return;}//定义两个栈SeqStack cur_path;SeqStack short_path;//分别对这两个栈进行初始化SeqStackInit(&cur_path);SeqStackInit(&short_path);//辅助递归_GetShortPathWithCircle(maze, entry, entry, &cur_path, &short_path, prev);SeqStackDebugPrint(&short_path, "最短路径");
}

                                这里写图片描述

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

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

相关文章

UVa1583

【题目描述】 传送门 【题目分析】 我以为很简单就写了一个暴力没有想到超时了。应该是T是非常大的所以必须得打表&#xff0c;将所有的结果都储存起来然后直接输出。 以后遇到这种可以一下算出所有结果的多组数据最好还是算出所有的结果然后再输出答案。 【AC代码】 #inc…

C 结构体嵌套一级指针 二级指针 动态分配内存

https://blog.csdn.net/xielinhua88/article/details/51364623 点击打开链接 #define _CRT_SECURE_NO_WARNINGS #include <stdlib.h> #include <string.h> #include <stdio.h> //结构体嵌套一级指针 二级指针 动态分配内存 typedef struct _Teacher { int ag…

线程的同步与互斥

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

二级指针与指针数组的关系

http://blog.csdn.net/shuaishuai80/article/details/6129742 #include <stdio.h> void test(char *argv[]); int main(void) { char *argv[3]{{"abcdefg"},{"1234567"},{"q1w2e3r"}}; test(argv); /*调用指针数组…

UVa1584

【题目描述】 传送门 【题目分析】 也是一道简单的模拟题&#xff0c;1A嘿嘿嘿。 再看书发现和书上的做法差不多。 【AC代码】 #include<cstdio> #include<cstring> #include<cmath> #include<algorithm> #include<queue> #include<cstd…

cf#582div3 D——暴力

【题目描述】 The only difference between easy and hard versions is the number of elements in the array.You are given an array a consisting of n integers. In one move you can choose any ai and divide it by 2 rounding down (in other words, in one move you c…

C语言 可变参数

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

UVa1585

【题目描述】 传送门 【题目分析】 氵 【AC代码】 #include<cstdio> #include<cstring> #include<cmath> #include<algorithm> #include<queue> #include<cstdlib> #include<set> #include<map> #include<vector>u…

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

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

进程间关系和守护进程

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

UVa1586

【题目描述】 传送门 【题目分析】 氵 【AC代码】 #include<cstdio> #include<cstring> #include<cmath> #include<algorithm> #include<queue> #include<cstdlib> #include<set> #include<map> #include<vector> …

猴子偷桃问题

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

UVa1225

【题目描述】 传送门 【题目分析】 做题做多了慢慢都忘记暴力了&#xff0c;想要快速算出来&#xff0c;找到规律&#xff0c;但是找来找去好复杂的都没有找到&#xff0c;然后写了一个不能再暴力的写法&#xff0c;就过了。。。 我还是觉得如果数据范围变成1e9那种级别的还…

linux 线程学习之条件变量

http://blog.csdn.net/hemmanhui/article/details/4417433 互斥锁&#xff1a;用来上锁。 条件变量&#xff1a;用来等待&#xff0c;当条件变量用来自动阻塞一个线程&#xff0c;直到某特殊情况发生为止。通常条件变量和互斥锁同时使用。 函数介绍&#xff1a; 1&#xff0e;…

UVa455

【题目描述】 传送门 【题目分析】 就是一个简单的暴力&#xff0c;只是需要注意输出格式比较毒瘤。 【AC代码】 #include<cstdio> #include<cstring> #include<cstdlib> #include<algorithm> #include<iostream> #include<cmath> #i…

网络相关基础概念

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

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

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

UVa227

【题目描述】 传送门 【题目分析】 题目的意思很简单&#xff0c;只是输入输出很毒瘤&#xff0c;我一开始用的fgets然后用scanf(" ")吃掉所有的空格和换行&#xff0c;可是这样有可能将迷宫的空格吃掉&#xff08;例如这个空格恰好在第一行第一列&#xff09;。 …

点对点数据链路层

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

UVa232

[题目描述] 传送门 [题目分析] 简单的模拟,注意细节 [AC代码] #include<cstdio> #include<cstring> #include<algorithm> #include<climits> #include<cctype> #include<queue> #include<set>using namespace std;typedef long…