迷宫求解(使用队列

240 篇文章 7 订阅
52 篇文章 2 订阅

在迷宫中,从入口到出口往往有一条或者多条最短路径。可以使用队列来求解迷宫的最短路径,使用队列时,搜索路径是一层一层向前推进,第一次找到出口是搜索的层数最少,这种搜索方法与广度优先算法类似。
  使用队列Qu记录走过的方块,该队列的结构如下:

struct{
	int i;   //方块的行号
	int j;   //方块的列号
	int pre; //前一方块在队列中的下标
}Qu[MaxSize];  //定义顺序队列
int front=0,rear=0; //定义队头和队尾指针并置初值为0

这里使用的队列Qu不是环形队列,为什么不采用环形队列呢?因为元素出队后,还要利用它输出路径,所以不将出队元素真正地删除。
  搜索从(x1,y1)到(x2,y2)路径的过程是:首先将(x1,y1)入队,在队列Qu不为空时循环,出队一次(由于不是环形队列,该出队元素仍在队列中),称该出队的方块为当前方块,front为该方块在Qu中的下标。
  如果当前方块为出口,则输出路径并结束。否则,按顺时针方向找出当前方块的4个方位中可走的相邻方块(对应的mg数组为0),将这些可能的相邻方块均插入到队列Qu中,其pre设置为搜索路径中上一个方块在Qu中的下标值,也就是当前方块的front值,并将相邻方块对应的mg数组值置为-1,以避免重复搜索。如果队列为空,表示未找到出口,即不存在路径。
  如图(1)所示的迷宫,求它从起点到终点所有的最短路径。


代码如下:
  //migong.cpp

#include <stdio.h>
#include <stdlib.h>
#define MaxSize 100
#define M1 6   //迷宫的最大行数
#define N1 6   //迷宫的最大列数
struct {
    int i;   //方块的行号
    int j;   //方块的列号
    int pre; //前一方块在队列中的下标
}Qu[MaxSize];  //定义顺序队列
int front = 0, rear = 0; //定义队头和队尾指针并置初值为0

int mg1[M1][N1] = {  //1: 代表墙,0: 代表通道
    { 1,1,1,1,1,1 },
    { 1,0,0,0,1,1 },
    { 1,0,1,0,0,1 },
    { 1,0,0,0,1,1 },
    { 1,0,0,0,0,1 },
    { 1,1,1,1,1,1 }
};

int minlen = 0;  //最短路径长度
int num = 1;   //路径计数

               //从队列中输出路径
void print1(int front) {
    int k = front, j;
    int ns = 0;
    do
    {
        j = k;
        k = Qu[k].pre;
        ns++;
    } while (k != -1);
    if (num == 1) minlen = ns;
    if (ns == minlen)
    {
        ns = 0;
        k = front;
        printf("  第%d条最短路径(反向输出): \n", num++);
        do
        {
            j = k;
            printf("\t(%d,%d)", Qu[k].i, Qu[k].j);
            k = Qu[k].pre;
            if (++ns % 5 == 0) printf("\n");
        } while (k != -1);
        printf("\n");
    }
}

//搜索路径为: (x1,y1) --> (x2,y2)
void mgpath1(int x1, int y1, int x2, int y2) {
    int i, j, find = 0, di, k;
    rear++;
    Qu[rear].i = x1; Qu[rear].j = y1;
    Qu[rear].pre = -1; //(x1,y1)入队
    while (front <= rear)
    {
        front++;
        for (di = 0; di < 3; di++)
        {
            switch (di) {
            case 0: i = Qu[front].i - 1; j = Qu[front].j;
                break;
            case 1: i = Qu[front].i; j = Qu[front].j + 1;
                break;
            case 2: i = Qu[front].i + 1; j = Qu[front].j;
                break;
            case 3: i = Qu[front].i; j = Qu[front].j - 1;
                break;
            }
            //方块(i,j)不越界,且可走
            if (i > 0 && j > 0 && mg1[i][j] == 0
                && (i != Qu[Qu[front].pre].i || j != Qu[Qu[front].pre].j))
            {
                rear++;
                Qu[rear].i = i; Qu[rear].j = j;
                Qu[rear].pre = front; //指向路径中上一个方块的下标
            }
        }
    }
    for (k = 0; k <= rear; k++)
    {
        if (Qu[k].i == x2 && Qu[k].j == y2) //找到了出口,输出路径
        {
            find = 1;
            print1(k);
        }
    }
    if (!find)
        printf("不存在路径!\n");

}

int main()
{
    printf("所有迷宫([1,1]->[4,4])最短路径\n");
    mgpath1(1, 1, M1 - 2, N1 - 2); //(1,1)->(M1-2,N1-2)

    system("pause"); //窗口暂停
    return 0;
}

效果如下:

图(2) 从起点到终点的最短路径有:4条(反向输出)

  • 5
    点赞
  • 73
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
队列是一种使用链表实现的队列数据结构。它具有队列的基本操作,如进队、出队、判断队空和求队中元素个数等。在求解迷宫问题时,可以使用队列来实现路径的搜索和记录。 以下是使用Java实现链队列求解迷宫的示例代码: ```java import java.util.LinkedList; import java.util.Queue; public class MazeSolver { private static final int[][] DIRECTIONS = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}}; // 上下左右四个方向 public static void solveMaze(int[][] maze, int startX, int startY, int endX, int endY) { int rows = maze.length; int cols = maze[0].length; boolean[][] visited = new boolean[rows][cols]; // 记录每个位置是否已经访问过 int[][] prev = new int[rows][cols]; // 记录每个位置的前驱位置,用于最后回溯路径 Queue<int[]> queue = new LinkedList<>(); // 使用队列存储待访问的位置 queue.offer(new int[]{startX, startY}); visited[startX][startY] = true; while (!queue.isEmpty()) { int[] curr = queue.poll(); int currX = curr[0]; int currY = curr[1]; if (currX == endX && currY == endY) { break; // 找到终点,结束搜索 } for (int[] direction : DIRECTIONS) { int nextX = currX + direction[0]; int nextY = currY + direction[1]; if (nextX >= 0 && nextX < rows && nextY >= 0 && nextY < cols && maze[nextX][nextY] == 0 && !visited[nextX][nextY]) { queue.offer(new int[]{nextX, nextY}); visited[nextX][nextY] = true; prev[nextX][nextY] = currX * cols + currY; // 记录前驱位置 } } } if (!visited[endX][endY]) { System.out.println("No path found."); // 没有找到路径 return; } // 回溯路径 int currX = endX; int currY = endY; while (currX != startX || currY != startY) { int prevX = prev[currX][currY] / cols; int prevY = prev[currX][currY] % cols; maze[currX][currY] = 2; // 标记路径 currX = prevX; currY = prevY; } maze[startX][startY] = 2; // 标记起点 maze[endX][endY] = 2; // 标记终点 // 打印迷宫和路径 for (int[] row : maze) { for (int cell : row) { if (cell == 0) { System.out.print("□ "); // 未访问的位置 } else if (cell == 1) { System.out.print("■ "); // 墙壁 } else { System.out.print("★ "); // 路径 } } System.out.println(); } } } ``` 使用上述代码,可以通过调用`solveMaze`方法来求解迷宫。其中,`maze`是一个二维数组表示迷宫,0表示可通行的位置,1表示墙壁,`startX`、`startY`表示起点的坐标,`endX`、`endY`表示终点的坐标。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值