带环迷宫递归求解

有多条通路且带环的迷宫如图所示:

这里写图片描述

如果我们采用只有一条通路的迷宫的解决办法,https://blog.csdn.net/virgofarm/article/details/80081804,就会直接从如下图所示的红线走出迷宫

这里写图片描述

但是由于还有其他路线,且出口一致,所以不能采用封路的办法,我们可以这样做,走每一步之前,先用当前位置的值加一标记下一步要走的位置,判断下一步是否是通路除了,值为一,也可以是,当前位置的值小于下一步位置的值。解决迷宫问题的思维导图如下这里写图片描述具体代码实现如下, 所依赖的栈可参考https://blog.csdn.net/virgofarm/article/details/80065574

Maze.h

#pragma once
#define MAX_ROW 4
#define MAX_COL 4

typedef struct Position
{
    int _x;
    int _y;
}Position;

typedef struct Maze
{
    int _map[MAX_ROW][MAX_COL];

}Maze, *PMaze;

void InitMaze(PMaze pm, int map[][MAX_COL]);//初始化
int _PassMaze(PMaze pm, Position entry, Position cur, PStack PPath, PStack PShortPath);//真正走迷宫
int IsExit(PMaze pm, Position cur, Position entry);//检测是否是出口
int IsValidEntry(PMaze pm, Position entry);//检测入口是否合法
void PassMaze(PMaze pm, Position entry, PStack ps);//提供给用户的走迷宫函数
void PrintMaze(PMaze pm, int map[][MAX_COL]);//打印迷宫

Maze.c

#include "stack.h"
#include "Maze.h"


//打印迷宫
void PrintMaze(PMaze pm)
{
    int i = 0;
    assert(pm);

    for (; i < MAX_ROW; ++i)
    {
        int j = 0;
        for (; j < MAX_COL; ++j)
        {
            printf("%d ", pm->_map[i][j]);
        }
        printf("\n");
    }

}

//迷宫初始化,就是将地图中的值赋给迷宫
void InitMaze(PMaze pm, int map[][MAX_COL])
{
    int i = 0;
    assert(pm);

    for (; i < MAX_ROW; ++i)
    {
        int j = 0;
        for (; j < MAX_COL; ++j)
        {
            pm->_map[i][j] = map[i][j];
        }
    }
}


//检测迷宫入口是否合法
int IsValidEntry(PMaze pm, Position entry)
{
    assert(pm);

    //必须位于迷宫边界且值为1
    if ((entry._x == 0 || entry._y == 0 || entry._x == MAX_ROW - 1
        || entry._y == MAX_COL - 1) && (pm->_map[entry._x][entry._y] == 1))
        return 1;
    return 0;
}

int IsPass(PMaze pm, Position cur, Position next)
{
    assert(pm);

    //next值为1且不能越界
    if ((next._x >= 0 && next._x <= MAX_ROW - 1) &&
        (next._y >= 0 && next._y <= MAX_COL - 1) &&
        pm->_map[next._x][next._y] == 1)
        return 1;
    //next值大于cur值且不能越界
    if ((cur._x >= 0 && cur._x <= MAX_ROW - 1) &&
        (cur._y >= 0 && cur._y <= MAX_COL - 1) &&
        pm->_map[cur._x][cur._y] < pm->_map[next._x][next._y])
        return 1;

    return 0;

}

//检测是否是出口
int IsExit(PMaze pm, Position cur, Position entry)
{
    assert(pm);

    //因为之前已经走过了,所以只要处于边界且不是入口肯定是出口
    if ((cur._x == 0 || cur._x == MAX_ROW - 1 ||
        cur._y == 0 || cur._y == MAX_COL - 1) &&
        ((cur._x != entry._x) || (cur._y != entry._y)))
        return 1;
    return 0;

}

void UpdatePath(PStack PPath, PStack PShortPath)
{
    int i = 0;
    int size = 0;
    assert(PPath);
    assert(PShortPath);

    PShortPath->size = PPath->size;
    size = PPath->size;

    for (; i < size; i++)
        PShortPath->arr[i] = PPath->arr[i];
}

int _PassMaze(PMaze pm, Position entry, Position cur, PStack PPath, PStack PShortPath)
{
    Position next;

    assert(pm);
    assert(PPath);
    assert(PShortPath);

    //栈如果为空说明进来的是入口
    if (!StackSize(PPath))
        pm->_map[cur._x][cur._y] = 2;
    StackPush(PPath, cur);

    //判断是否为出口
    if (IsExit(pm, cur, entry))
    {
        //更新最短路径:1.PShortPath为空2.PShortPath的size大于PPath的size
        if (StackEmpty(PShortPath))
            UpdatePath(PPath, PShortPath);
        if (StackSize(PPath) < StackSize(PShortPath))
            UpdatePath(PPath, PShortPath);

        //将PPath中的栈顶元素出栈,继续找路径
        StackPop(PPath);
    }

    //上
    next = cur;
    next._x -= 1;
    if (IsPass(pm, cur, next))
    {
        //先用cur的值加1标记next位置,再走next
        pm->_map[next._x][next._y] = pm->_map[cur._x][cur._y] + 1;
        _PassMaze(pm, entry, next, PPath, PShortPath);
    }

    //左
    next = cur;
    next._y -= 1;
    if (IsPass(pm, cur, next))
    {
        pm->_map[next._x][next._y] = pm->_map[cur._x][cur._y] + 1;
        _PassMaze(pm, entry, next, PPath, PShortPath);
    }

    //右
    next = cur;
    next._y += 1;
    if (IsPass(pm, cur, next))
    {
        pm->_map[next._x][next._y] = pm->_map[cur._x][cur._y] + 1;
        _PassMaze(pm, entry, next, PPath, PShortPath);
    }

    //下
    next = cur;
    next._x += 1;
    if (IsPass(pm, cur, next))
    {
        pm->_map[next._x][next._y] = pm->_map[cur._x][cur._y] + 1;
        _PassMaze(pm, entry, next, PPath, PShortPath);
    }

    //说明cur走错了
    StackPop(PPath);
    return 0;
}

void PassMaze(PMaze pm, Position entry, PStack ps)
{
    Stack PShortPath;

    assert(pm);
    assert(ps);

    //先判断迷宫入口是否合法
    if (!IsValidEntry(pm, entry))
    {
        printf("迷宫入口非法!!!\n");
        return;
    }
    //开始真的走进入口
    _PassMaze(pm, entry, entry, ps, &PShortPath);
}

test.c

#include "stack.h"
#include "Maze.h"
#include <windows.h>


void TestMaze(PStack ps)
{
    int i = 0;
    Position entry;
    Maze m;
    PMaze pm = &m;
    StackInit(ps, 10);
    int map[4][4] = { { 0, 0, 0, 0 },
                      { 0, 1, 1, 0 },
                      { 0, 1, 1, 1 },
                      { 0, 1, 0, 0 }};
    InitMaze(pm, map);
    PrintMaze(pm, map);
    entry._x = 3;
    entry._y = 1;
     PassMaze(pm, entry, ps);//带环迷宫递归
    printf("\n");
    PrintMaze(pm, map);


}
int main()
{
    Stack s;
    PStack ps = &s;

   TestMaze(ps);//测试迷宫
    system("pause");
    return 0;
}

猜你喜欢

转载自blog.csdn.net/virgofarm/article/details/80085248
今日推荐