迷宫(回溯算法)

要想解决迷宫问题,首先搞明白八皇后,迷宫问题是回溯和贪心的产物。
题目:现有一个迷宫如图:
这里写图片描述
黄色五角星为迷宫的起点,红色五角星为迷宫的终点。
要求:找到从起点到终点的所有路线。
思路:我们的目的为了到达终点,所以一定要向着终点的方向出发。
因为迷宫的终点在起点的右下角。
所以我们选择路径时先考虑向下走,
走不通考虑向右走,
走不通考虑向上,
最后考虑向左。
这样就会总有一次到达终点。
思路
1、将“小人”放到起点。
2、判断这个方向是否能走,(起始方向向下)
(1)如果能走,走这条路,并记录这条路已经被走过了
(2)如果不能走,
(a)换个方向,重复步骤 2。如果4个方向都不能走,退回上一步的位置,擦掉这条路被走过的记录,并重复步骤2。
3、如果下一步的坐标是终点坐标,说明一条路径已经诞生了。输出这条路径。并退回上一步,重复步骤2中的(a),继续探索下一条路径。
思考
什么时候“小人”将所有路径走完?
“小人”将起点向上开始走到终点的路径都走完。(此题的迷宫起点向上和向左是没有路的,所以应该是“小人”从起点开始向右走过的路径都走完)
算法实现

首先声明一个数组用来存储方向:

int move[4][2] = { { 1, 0 }, { 0, 1 }, { -1, 0 }, { 0, -1 } };//分别代表向下、向右、向上、向左

当前位置的坐标加上指定的数组元素,就是下一步的坐标。
定义迷宫:

Maze[9][10];

为了记录走过的路:定义一个迷宫副本:

copyMaze[9][10];

记录路线(每一步的坐标):

way[100][2] = { { 1, 1 } };//用来存储路线(将起点坐标添加进去)

约定:
迷宫数组中:
墙为0、路为-1。
具体实现方法:

#include<stdlib.h>
#include<stdio.h>
#include<windows.h>
int Maze[9][10] = { 0 };
int move[4][2] = { { 1, 0 }, { 0, 1 }, { -1, 0 }, { 0, -1 } };//分别代表向下、向右、向上、向左
int way[100][2] = { { 1, 1 } };//用来存储路线(将起点坐标添加进去)
int copyMaze[9][10] = { 0 };//用来记录走过的路
int top = 0;//用来记录步数,并用来指向最后一步的坐标
int count = 0;//用来统计有多少种走法
//制作迷宫路线
void makeAMap(){
    //制作迷宫的路线
    Maze[1][1] = Maze[1][2] = -1;
    Maze[2][1] = Maze[2][2] = Maze[2][3] = -1;
    Maze[3][1] = Maze[3][2] = Maze[3][3] = Maze[3][4] = Maze[3][5] = Maze[3][6] = -1;
    Maze[4][3] = Maze[4][1] = Maze[4][4] = Maze[4][6] = -1;
    Maze[5][1] = Maze[5][4] = Maze[5][6] = Maze[5][7] = Maze[5][8] = -1;
    Maze[6][1] = Maze[6][2] = Maze[6][4] = Maze[6][5] = Maze[6][6] = Maze[6][8] = -1;
    Maze[7][6] = Maze[7][7] = Maze[7][8] = -1;
}
//将路径添加到迷宫中
void addWay(){
    int go = top;
    Maze[1][1] = 1;
    for (int tag = top; tag > -1; tag--){
        Maze[way[tag][0]][way[tag][1]] = 1 + go--;
    }
}
//在迷宫删除上一条路径
void delWay(){
    for (int tag = top; tag > -1; tag--){
        Maze[way[tag][0]][way[tag][1]] = -1;
    }
}
//打印迷宫
void printMap(){
    printf("第%d组\n", ++count);
    int num = 0;
    unsigned int block = 32936;
    unsigned int blank = 8224;
    addWay();
    printf("  0 1 2 3 4 5 6 7 8 9\n");
    for (int i = 0; i < 9; i++){
        printf("%d ", num++);
        for (int j = 0; j < 10; j++){
            if (Maze[i][j] == 0){
                printf("%s", &block);
            }
            else if (Maze[i][j] == -1){
                printf("%s", &blank);
            }
            else{
                printf("%2d", Maze[i][j]);
            }
        }
        printf("\n");
    }
    printf("\n\n");
    delWay();
}

void maze(int x, int y){
    for (int i = 0; i < 4; i++){

        int a = x + move[i][0];
        int b = y + move[i][1];

        if (Maze[a][b] && !copyMaze[a][b]){
            //如果有路,并且没有被走过

            copyMaze[a][b] = 1;//走这条路

            //记录这条路已经被走过了
            way[++top][0] = a;
            way[top][1] = b;

            if (a == 7 && b == 8){
                printMap();
            }
            else{
                maze(a, b);
            }
            //回到上一步,并擦除这一步的痕迹
            top--;
            copyMaze[a][b] = 0;
        }
    }
}
int main(void){
    makeAMap();
    copyMaze[1][1] = -1;
    maze(1,1);
    system("pause");
    return 0;
}

调试结果:
这个迷宫一共有56种走法:
第1种:
这里写图片描述
第56种:
这里写图片描述
注意第二部的位置,以此验证思考题。

  • 4
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Java 实现迷宫回溯算法的基本思路是采用递归的方式找出所有可能的路径,然后选择最优解。下面是一个简单的迷宫回溯算法示例代码: ```java public class MazeSolver { private int[][] maze; // 迷宫地图 private int[][] solution; // 解决方案 private int mazeSize; // 迷宫大小 private int startX, startY; // 起点坐标 private int endX, endY; // 终点坐标 public MazeSolver(int[][] maze) { this.maze = maze; this.mazeSize = maze.length; this.solution = new int[mazeSize][mazeSize]; } public void solve(int x, int y) { if (x == endX && y == endY) { // 到达终点 solution[x][y] = 1; printSolution(); // 输出解决方案 } if (isValid(x, y)) { // 当前位置可行 solution[x][y] = 1; // 标记为已经访问 solve(x + 1, y); // 向下探索 solve(x, y + 1); // 向右探索 solve(x - 1, y); // 向上探索 solve(x, y - 1); // 向左探索 solution[x][y] = 0; // 标记为未访问 } } // 判断当前位置是否可行 private boolean isValid(int x, int y) { if (x < 0 || x >= mazeSize || y < 0 || y >= mazeSize) { return false; } if (maze[x][y] == 0 || solution[x][y] == 1) { return false; } return true; } // 输出解决方案 private void printSolution() { for (int i = 0; i < mazeSize; i++) { for (int j = 0; j < mazeSize; j++) { System.out.print(solution[i][j] + " "); } System.out.println(); } System.out.println(); } } ``` 上述代码中,`maze` 表示迷宫地图,`solution` 表示解决方案,`startX`、`startY` 表示起点坐标,`endX`、`endY` 表示终点坐标。在 `solve` 方法中,首先判断当前位置是否到达终点,如果到达,则输出解决方案;否则,依次向下、向右、向上、向左探索。在探索之前,需要判断当前位置是否可行,即没有越界并且不是障碍物。如果当前位置不可行,则返回上一步进行回溯。 使用迷宫回溯算法解决迷宫问题的时间复杂度为指数级别,因此对于较大的迷宫问题,效率会比较低。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值