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

原创 2018年04月17日 14:46:35

求解多出口迷宫的最短路径,是在基于求解简单迷宫是否存在路径的问题的基础上的一个提高。我们首先需要认识到的是,不论是求解简单迷宫问题,还是复杂迷宫的问题,我们都需要基于栈,使用回溯法来解决问题。

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

                       

图中0表示墙,即无法落脚;1表示可以落脚;之后我们会用2来标记走过的路。

我们默认出口为四个边界上的点。若入口也为边界点,则出口与入口不能重合。

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;
}

通过代码我们可以认识到,由于多出口迷宫存在着多条路径,所以我们需要定义两个栈,一个栈中存放着当前走过的路径的数据,另一个栈中存放着最短路径的数据。每找到一条路径,就将当前路径的长度与最短路径的长度作比较,若存放最短路径的栈为空栈,或者当前路径的长度小于最短路径的长度,就用存放着当前路径的栈中的数据替代存放最短路径的栈中的数据。当所有路径都找到以后,此时存放最短路径的栈中的数据即可表示该迷宫的最短路径。


结果演示:

          

【数据结构】求多出口带环迷宫的最短路径(递归版本)

Maze.h #pragma once #include typedef struct Pos{ int _Row; int _COL; }Pos; typedef struct Maz...
  • Qregi
  • Qregi
  • 2018-02-03 22:17:49
  • 66

[数据结构]求解迷宫最短路径问题

一、问题概述        之前,我们了解了如何实现迷宫问题(对于迷宫只有一个出口可以通的情况),事实上我们的迷宫有多个出口,对于每条路径来说,有长有短,所以在这里,我们讨论一下迷宫的最短路径,...
  • xxpresent
  • xxpresent
  • 2016-12-08 16:23:59
  • 1679

erl_stack_queue-队列求迷宫最短路径

求迷宫的最短路径: 现要求设计一个算法找一条从迷宫入口到出口的最短路径。本算法要求找一条迷宫的最短路径,算法的基本思想为:从迷宫入口点(2,2)出发,向四周搜索,记下所有一步能到达的坐标点;然后依次...
  • u011518176
  • u011518176
  • 2015-09-14 11:31:11
  • 287

求迷宫的最短路径:现要求设计一个算法找一条从迷宫入口到出口的最短路径。

  • 2009年11月25日 23:06
  • 6KB
  • 下载

迷宫问题的最短路径

“test.cpp” #define _CRT_SECURE_NO_WARNINGS 1 #include using namespace std; #include #define ROW 1...
  • poison_biti
  • poison_biti
  • 2016-09-11 21:06:19
  • 292

迷宫最短路径问题(ShortestPath)的求解——利用链式队列

迷宫最短路径问题(ShortestPath)的求解——利用链式队列 注:借助于栈求解迷宫问题时,并不能保证找到一条从迷宫入口到迷宫出口的最短路径。而借助于队列,可以找到从迷宫入口到迷宫出口的最短路径...
  • cainv89
  • cainv89
  • 2016-06-05 12:09:15
  • 2612

迷宫问题并求最短路径

#include  #include  #include  #include  struct Pos { int _row; int _col; }; bool MinPath(vector>...
  • fucangzxx
  • fucangzxx
  • 2016-05-29 21:36:15
  • 309

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

代码如下: Maze.h #pragma once #include typedef struct Pos{ int _Row; int _COL; }Pos; Maze.c ...
  • Qregi
  • Qregi
  • 2018-02-01 18:02:46
  • 94

求解迷宫问题的所有路径及最短路径程序

路障  路障  路障  路障  路障  路障  路障  入口   ...
  • cncnlg
  • cncnlg
  • 2014-11-07 21:45:07
  • 1229

迷宫最短路径问题解析

有一个二维数组,0表示路,-1表示墙,求其中任意两点的最短路径。 我们先看,怎么求一条路径:求两点路径是一个数据结构上的典型的迷宫问题,很多数据结构的书上都有介绍,解决办法如下: 从一点开...
  • a1259109679
  • a1259109679
  • 2015-08-29 09:47:07
  • 7724
收藏助手
不良信息举报
您举报文章:求解多出口迷宫最短路径的问题
举报原因:
原因补充:

(最多只允许输入30个字)