[Data structure]------Multi-path maze with ring to find the shortest path (C language)

Idea: When solving the previous function, we judge whether the function can be settled, and the functions marked to be settled are universal, and now because the path of the maze is looped, if we are using the above-mentioned multi-loop without loops The method of finding the shortest path by the path is definitely wrong, so for the solution of the maze with a ring, we can no longer simply mark it as 2, we should mark the number of steps taken, so that we can judge whether it can be When landing, you can directly judge whether the number of steps in the next step is larger than the number of steps we are about to mark.

1) Determine whether the current point can be settled, if not, return directly
2) Mark the current point if it can, and insert the current point into cur_path
3) Determine whether the current point is an exit, if it is an exit, it means that a road has been found
4) Compare this path with the shortest path, and save the shorter path into the shortest path
5) No matter whether the current path is the shortest path, backtracking is performed, and backtracking to the previous point to continue to find other paths
6) If it is not an exit , then detect the adjacent 4 points, (using the clockwise method to backtrack) call the function itself every time a point is detected, and repeat the actions 1~6.
7) If we have probed all four directions, we can pop the stack (the top element of the stack of cur_path, short_path is popped) and backtrack to the previous point

Implementation of the code:


/////////////////////////////////////////////////////////
/////////////////带环多通路最短路径//////////////////////
/////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////


void MazeInitCycle(Maze *maze)
{
    int map[ROW][COL] =
    {
        { 0, 1, 0, 0, 0, 0 },
        { 0, 1, 1, 1, 0, 0 },
        { 1, 1, 0, 1, 0, 0 },
        { 0, 1, 1, 1, 1, 1 },
        { 0, 1, 0, 0, 0, 0 },
        { 0, 1, 0, 0, 0, 0 }
    };
    int i = 0;
    for (; i < ROW; i++)
    {
        int j = 0;
        for (; j < COL; j++)
        {
            maze->map[i][j] = map[i][j];
        }
    }
}
//判断是否能落脚的函数
int CanStayWithCycle(Maze *maze, Point cur, Point pre)
{
    //在地图外的点都不能落脚
    if (cur.row < 0 || cur.row >= ROW || cur.col < 0 || cur.col >= COL)
    {
        return 0;
    }
    //在地图内的点,且值为1就能直接落脚
    int cur_value = maze->map[cur.row][cur.col];
    int pre_value = maze->map[pre.row][pre.col];
    if (cur_value == 1)
    {
        return 1;
    }
    //当前点如果已经走过了,比较cur对应的值和pre对应的值
    //cur-value = 7,pre-value = 5应该落脚
    //cur-value = 6,pre-value = 5不应该落脚
    //cur-value = 5,pre-value = 5不应该落脚
    //cur-value = 4,pre-value = 5不应该落脚

    //cur-value > pre-value+1就应该落脚
    if (cur_value > pre_value + 1)
    {
        return 1;
    }
    return 0;
}
//标记函数
void MarkWithCycle(Maze *maze, Point cur, Point pre)
{
    if (pre.row == -1 && pre.col == -1)
    {
        //针对入口点进行标记,此时的pre是一个非法点
        //不能根据pre_value+1的方法进行标记
        //由于地图中我们用1表示路,所以这里对于入口点直接标记为2,所以对于后面的标记的数字的意义就是对该数字-1就是从入口点走到该点的所需的步数
        maze->map[cur.row][cur.col] = 2;
        return;
    }
    int pre_value = maze->map[pre.row][pre.col];
    maze->map[cur.row][cur.col] = pre_value + 1;
}
//每次走到下一个点都会递归的调用这个函数
void GetCycleShort(Maze *maze, Point cur, Point pre, Point entry, SeqStack *cur_path, SeqStack *short_path)
{
    if (maze == NULL || cur_path == NULL || short_path == NULL)
    {
        return;
    }
    //判断当前点是否能落脚(判定规则改变了)
    if (!CanStayWithCycle(maze, cur, pre))
    {
        //不能落脚就直接返回
        return;
    }
    //能落脚就把当前点标记(标记规则也改变了)并且入cur_path栈,cur_path栈保存着我们走过的路径
    MarkWithCycle(maze, cur, pre);
    SeqStackPush(cur_path, cur);
    //更新pre的值,后续判断是否可以落脚标记
    pre = cur;
    //判定当前点是否为出口
    if (IsExit(maze, cur, entry))
    {
        //是出口说明找到了一条路
        printf("找到了一条路\n");
        //将cur_path与short_path进行比较
        if (short_path->size == 0 || cur_path->size < short_path->size)
        {
            printf("找到了一条比较短的路\n");
            //把比较短的路径保存到short_path栈中
            SeqStackAssgin(cur_path, short_path);
        }
        //不管当前的路径是否为最短的路径都要进行回溯,回到前一个点继续找其他的路径
        SeqStackPop(cur_path);
        return;
    }
    //如果不是出口,以当前点为基准点,探测相邻的四个点
    Point up = cur;
    up.row--;
    GetCycleShort(maze, up, pre, entry, cur_path, short_path);

    Point right = cur;
    right.col++;
    GetCycleShort(maze, right, pre, entry, cur_path, short_path);

    Point down = cur;
    down.row++;
    GetCycleShort(maze, down, pre, entry, cur_path, short_path);

    Point left = cur;
    left.col--;
    GetCycleShort(maze, left, pre, entry, cur_path, short_path);

    //如果四个方向都探测过了,就出栈回溯
    SeqStackPop(cur_path);
    return;
}

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325485631&siteId=291194637