【数据结构】求多出口迷宫的最短路径

本文介绍了如何使用代码解决多出口迷宫的最短路径问题,通过Maze.h和Maze.c两个文件展示了具体的算法实现。
摘要由CSDN通过智能技术生成

代码如下:

Maze.h

#pragma once

#include<stdio.h>

typedef struct Pos{
	int _Row;
	int _COL;
}Pos;


Maze.c

#define _CRT_SECURE_NO_WARNINGS 1
#include"Maze.h"
#include"Stack.h"

/*判断当前路径是否在地图上*/
int CanStay(Pos* pos, int Maze[5][5]) {
	if (pos == NULL) {
		return;
	}
	if (pos->_Row < 0 || pos->_COL < 0 ||
		pos->_Row > 4 || pos->_COL > 4) {
		/*当前点在地图外*/
		return 0;
	}
	return 1;
}

/*标记一个点*/
void MarkPos(Pos* pos, int Maze[5][5]) {
	if (pos == NULL) {
		return;
	}
	Maze[pos->_Row][pos->_COL] = 2;
}

/*检查该点是不是是通路*/
int CanWalk(Pos* pos, int Maze[5][5]) {
	if (pos == NULL) {
		return;
	}
	if (Maze[pos->_Row][pos->_COL] == 1) {
		return 1;
	}
	return 0;
}

/*检查该点是不是出口*/
int Check_Export(Pos* pos, int Maze[5][5]) {
	if (pos == NULL) {
		return;
	}
	if (pos->_Row == 0 || pos->_COL == 0 ||
		pos->_Row == 4 || pos->_COL == 4) {
		/*该点在地图边缘,判断该点是不是出口*/
		if (Maze[pos->_Row][pos->_COL] == 2 ) {
			return 1;
		}
	}
	return 0;
}

/*stack1这个栈是存储路径的结点的*/
/*stack2这个栈是存储路径的*/
int GetShortPath(Pos* entry, int Maze[5][5]) {
	if (entry == NULL) {
		return;
	}
	//判断当前入口点是否合法
	if (!CanStay(entry, Maze)) {
		return 0;
	}
	//然后把入口点标记
	MarkPos(entry, Maze);
	SeqStack stack1;
	SeqStack stack2;

	/*初始化两个栈*/
	SeqStackInit(&stack1);
	SeqStackInit(&stack2);

	Pos pos;
	pos._Row = entry->_Row;
	pos._COL = entry->_COL;
	/*pos_path是存储路径的长短的,row是第几个通路,用col表示第几条路径*/
	Pos pos_path;;
	/*初始化pos_path*/
	pos_path._Row = 0;
	pos_path._COL = 0;

	/*把入口点入栈*/
	SeqStackPush(&stack1, *entry);
	++pos_path._Row;

	//开始循环
	/*
	**与不是最短路径的区别是,设置一个len,每次入栈一个元素,就让len+1, 出栈一个元素,就len-1
	**创建一个栈,存储最短路径,如果遇到出口,如果栈为空,就把当前len入栈,反之就把当前的len和栈的栈顶元素比较
	**如果len大于栈顶元素,就回溯,反之就把当前len入栈,再回溯
	**知道找不到路走了,判断栈是否为空,如果为空就表示没有路径,如果不为空,就取栈顶元素,栈顶元素为最小路径
	**/
	//判断当前点是不是在地图上
	while (CanStay(&pos, Maze)) {

		/*上*/
		--pos._Row;
		/*如果该点在地图上*/
		if (CanStay(&pos, Maze)) {
			/*该点可以形成通路*/
			if (CanWalk(&pos, Maze)) {
				/*
				**检查是不是出口,如果是出口,就把pospath++,
				**如果栈stack2是空栈,就直接入栈pos和pospath
				**如果不是空栈,就把pospath和当前栈顶元素比较,如果小的话就入栈pospath
				**然后继续走下去,判断pos上一个位置的下一个方向
				*/
				/*如果可以走,就标记*/
				MarkPos(&pos, Maze);

				if (Check_Export(&pos, Maze)) {
					/*是出口*/
					++pos_path._Row;
					++pos_path._COL;

					SeqStackPush(&stack1, pos);

					/*判断当前栈是不是空栈然后判断通路的长短要不要入栈*/
					if (SeqStackEmpty(&stack2)) {
						/*是空栈把pos和pospath直接入栈*/
						SeqStackPush(&stack2, pos);
						SeqStackPush(&stack2, pos_path);
						/*然后继续判断当前点的下一个方向*/
					}
					else {
						/*不是空栈,比较当前路径和栈顶元素的row的大小*/
						Pos top_path = SeqStackTopValue(&stack2);
						if (pos._Row < top_path._Row) {
							/*当前路径短*/
							SeqStackPush(&stack2, pos);
							SeqStackPush(&stack2, pos_path);
						}
						/*如果当前路径比已经找到的长,那就继续判断*/
					}
				}
				/*
				**如果不是出口,把当前pos入栈,继续循环
				*/
				else {
					SeqStackPush(&stack1, pos);
					pos_path._Row++;
					continue;
				}
			}
		}
		++pos._Row;

		/*下*/
		++pos._Row;
		if (CanStay(&pos, Maze)) {
			if (CanWalk(&pos, Maze)) {
				/*如果可以走,就标记*/
				MarkPos(&pos, Maze);

				if (Check_Export(&pos, Maze)) {

					SeqStackPush(&stack1, pos);

					/*如果是出口*/
					//row代表路径的长度
					++pos_path._Row;
					++pos_path._COL;

					if (SeqStackEmpty(&stack2)) {
						/*如果是空栈,直接入栈*/
						SeqStackPush(&stack2, pos);
						SeqStackPush(&stack2, pos_path);
					}
					else {
						/*不是空栈*/
						Pos path = SeqStackTopValue(&stack2);
						if (pos_path._Row < path._Row) {
							/*如果小于*/
							SeqStackPush(&stack2, pos);
							SeqStackPush(&stack2, pos_path);
						}
						/*如果不小于就不管,继续判断当前点的下一个方向*/
					}
				}
				else {
					/*这个点可以走,但是不是出口点*/
					SeqStackPush(&stack1, pos);
					++pos_path._Row;
					continue;
				}
			}
		}
		--pos._Row;

		/*左*/
		--pos._COL;
		if (CanStay(&pos, Maze)) {
			if (CanWalk(&pos, Maze)) {

				/*如果可以走,就标记*/
				MarkPos(&pos, Maze);

				if (Check_Export(&pos, Maze)) {

				
					SeqStackPush(&stack1, pos);

					++pos_path._Row;
					++pos_path._COL;
					/*判断是不是空栈*/
					if (SeqStackEmpty(&stack2)) {
						/*是空栈*/
						SeqStackPush(&stack2, pos);
						SeqStackPush(&stack2, pos_path);
					}
					else {
						/*判断长短*/
						Pos path = SeqStackTopValue(&stack2);
						if (pos_path._Row < path._Row) {
							/*当前出口是路径较短的*/
							SeqStackPush(&stack2, pos);
							SeqStackPush(&stack2, pos_path);
						}
						/*如果不是短的就不管了,继续下一个方向*/
					}

				}
				else {
					/*是通路但是不是出口点*/
					SeqStackPush(&stack1, pos);
					pos_path._Row++;
					continue;
				}
			}
		}
		++pos._COL;
		/*右*/
		++pos._COL;
		if (CanStay(&pos, Maze)) {
			if (CanWalk(&pos, Maze)) {

				/*如果可以走,就标记*/
				MarkPos(&pos, Maze);

				if (Check_Export(&pos, Maze)) {

				
					SeqStackPush(&stack1, pos);

					pos_path._Row++;
					pos_path._COL++;

					if (SeqStackEmpty(&stack2)) {
						SeqStackPush(&stack2, pos);
						SeqStackPush(&stack2, pos_path);
					}
					else {
						Pos path = SeqStackTopValue(&stack2);
						if (pos_path._Row < path._Row) {
							SeqStackPush(&stack2, pos);
							SeqStackPush(&stack2, pos_path);
						}
					}
				}
				else {
					SeqStackPush(&stack1, pos);
					pos_path._Row++;
					continue;
				}
			}
		}
		--pos._COL;
		/*该循环的出口是,如果该点判断了上下左右了,不管走不走的通了,该点是入口点,就可以结束循环了*/
		if (pos._Row == entry->_Row && pos._COL == entry->_COL) {
			/*当前节点是入口点,而且四个方向都走不同*/
			break;
		}

		/*当前点走不通了,而且还不是入口点*/
		SeqStackPop(&stack1);
		Pos pos2 = SeqStackTopValue(&stack1);
		pos = pos2;
		pos_path._Row--;
	}
	/*如果有出口,那么此时最短路径是stack2的栈顶元素的row值,最短路径的出口是*/
	if (SeqStackEmpty(&stack2)) {
		/*如果此时stack2是空的,表示没有找到迷宫的出口*/
		return 0;
	}
	Pos len = SeqStackTopValue(&stack2);
	return len._Row;
}
Pos GetPath(SeqStack* stack) {
	if (stack == NULL) {
		return;
	}
	/*
	**获取最短路径
	*/
	SeqStackPop(stack);
	return SeqStackTopValue(stack);
}


int main() {
	/*求多出口迷宫的最短路径,非递归求法*/

	Pos entry;
	entry._Row = 0;
	entry._COL = 1;


	int maze[5][5] = {  { 0, 1, 0, 0, 0 },
						{ 0, 1, 1, 1, 0 },
						{ 0, 1, 0, 1, 1 },
						{ 1, 1, 0, 1, 0 },
						{ 0, 0, 0, 1, 0 },
						};
	int i = GetShortPath(&entry, maze);
	if (i == 0) {
		printf("未找到路径");
	}
	else {
		printf("最短路径为:%d", i);
	}
	system("pause");
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值