# 求解多出口迷宫最短路径的问题

• 首先，我们先来定义一个多出口的迷宫：

maze.h：
#pragma once
#include <stdio.h>
#include<stdlib.h>
#include<stddef.h>

#define MAX_ROW 6
#define MAX_COL 6

typedef struct Point{
int row;
int col;
}Point;
typedef Point SeqStackType;

typedef struct SeqStack{
SeqStackType *data;
size_t size;
size_t capacity;
}SeqStack;
typedef struct Maze{
int map[MAX_ROW][MAX_COL];
}Maze;
maze.c：
#include "maze.h"

int map[MAX_ROW][MAX_COL]={
{0,1,0,0,0,0},
{0,1,1,1,0,0},
{0,1,0,1,1,1},
{1,1,1,0,0,0},
{0,0,1,0,0,0},
{0,0,1,0,0,0}
};

void MazeInitShortPath(Maze* maze){//初始化
if(maze == NULL)
return;
size_t i = 0;
for(;i < MAX_ROW;i++){
size_t j = 0;
for(;j < MAX_COL;j++){
maze->map[i][j] = map[i][j];
}
}
return;
}

void SeqStackDebugPrint(SeqStack* stack,const char* msg){//走过的路径中每一个点的打印
printf("%s\n",msg);
if(stack == NULL)
return;
size_t i = 0;
for(;i < stack->size;i++){
printf("(%d,%d)\n",stack->data[i].row,stack->data[i].col);
}
printf("\n");
return;
}

void MazePrint(Maze* maze){//迷宫的打印
if(maze == NULL)
return;
size_t i = 0;
for(;i < MAX_ROW;i++){
size_t j = 0;
for(;j < MAX_COL;j++)
printf("%2d ",maze->map[i][j]);
printf("\n");
}
return;
}

int CanStay(Maze* maze,Point pt){//判断当前点是否能落脚
if(maze == 0)
return 0;
if(pt.row < 0 || pt.row >= MAX_ROW || pt.col < 0 || pt.col >= MAX_COL){//迷宫边界外，不能落脚
return 0;
}
int value = maze->map[pt.row][pt.col];
if(value == 1){//边界内，且可落脚
return 1;
}
return 0;
}

void Mark(Maze* maze,Point cur){//标记走过的路径
maze->map[cur.row][cur.col] = 2;
}

int IsExit(Maze* maze,Point cur,Point entry){//判断当前点是否为出口
(void)maze;
//1.判断当前点是不是入口，若为入口，则不是出口
if(cur.row == entry.row && cur.col == entry.col){
return 0;
}
//2.如果当前点在地图边界上，说明是出口
if(cur.row == 0 || cur.row == MAX_ROW-1 || cur.col == 0 || cur.col == MAX_COL-1){
return 1;
}
return 0;
}

void SeqStackAssgin(SeqStack* from,SeqStack* to){//将from中的数据全部拷贝至to中
//释放to中的原有内存
SeqStackDestroy(to);
//根据from中的元素个数确定内存申请的大小，给to重新申请一个足够的内存
to->size = from->size;
to->capacity = from->capacity;
to->data = (SeqStackType*)malloc(to->capacity * sizeof(SeqStackType));
//再进行数据拷贝
size_t i = 0;
for(;i < from->size;i++){
to->data[i] = from->data[i];
}
}

void _GetShortPath(Maze* maze,Point cur,Point entry,SeqStack* cur_path,SeqStack* short_path){//GetShortPath的辅助函数
printf("cur:(%d,%d)\n",cur.row,cur.col);
//1.判断当前点能否落脚
if(!CanStay(maze,cur)){
return;
}
//2.若能落脚，给当前位置做一个标记
//同时将当前点插入到cur_path
Mark(maze,cur);
SeqStackPush(cur_path,cur);
//3.若当前点为出口，说明找到了一条出口
if(IsExit(maze,cur,entry)){
printf("找到了一条路径\n");
if(cur_path->size < short_path->size || short_path->size == 0){
//将当前路径与short_path中的路径对比，若当前路径比short_path短或short_path本身为空栈，则用当前路径替换short_path
SeqStackAssgin(cur_path,short_path);
printf("找到了一条相对较短的路径\n");
}
//若当前路径没有比short_path短，就尝试找其他路径
SeqStackPop(cur_path);
return;
}
//4.若当前点不是出口，则按顺时针方向探测四个相邻的点，递归式调用函数自身，递归式更新cur节点
//（每次递归时，cur都是下一次要走的点，这个点能否落脚，交给递归函数作判断）
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);

//若四个方向都递归的探测过了，则可进行出栈，同时回溯到上一个点
SeqStackPop(cur_path);
return;
}

void GetShortPath(Maze* maze,Point entry){
SeqStack cur_path;
SeqStack short_path;
SeqStackInit(&cur_path);
SeqStackInit(&short_path);
_GetShortPath(maze,entry,entry,&cur_path,&short_path);
SeqStackDebugPrint(&short_path,"最短路径为");
return;
}

• 评论

• 下一篇
• 上一篇