算法设计-迷宫

一、目的

  • 正确应用蛮力法求解迷宫问题。
  • 对边界值测试结果。
  • 正确分析算法时间复杂度。

二、实验内容与设计思想

设计思路

(1) 输入迷宫规模n

(2) 随机生成n×n迷宫地图

(3) 深度遍历走迷宫

(4) 输出迷宫

主要数据结构

结构名数据结构
参数介绍&&方法
point类class Point():
def __init__(self, x, y):
self.x = x
self.y = y
参数介绍: x,y代表在迷宫内的位置 方法 point方法,输出位置
Maze类class Maze():
def __init__(self):
self.start = Point(0, 0)
self.maze = []
self.n = 5
self.road = []
self.correct_road = []
参数介绍
start:迷宫开始位置
maze:迷宫
n:迷宫的规模
road:路径
correct_road:所有可以走到重点的路径集合
方法
get_maze:获取随机迷宫
get_maze_prob:
获取随机迷宫(获得0的概率0.7)
print:输出路径
go:实现迷宫探索
main:主方法

主要代码结构

三、实验使用环境

软件:Python 3.9.7

PyCharm 2021.3.1

平台:win10

四、实验步骤和调试过程

4.1 生成迷宫

参数

输入:n------迷宫的规模
输出:无

步骤

使用random.randint函数生成n行n列的迷宫,并打印出来。

测试

  • 测试点1:1-10: 随机抽取10个

  • 测试点2:-100-100:随机抽取10个

  • 测试点3:-1000-1000:随机抽取10个

<img src="http://akavjht.top/image/0022/image6.png"width=“15px” style=“width:15px;”> 结果

请输入迷宫的大小:-999
请重新输入
请输入迷宫的大小:0
请重新输入
请输入迷宫的大小:9
迷宫为:
[0, 0, 0, 0, 1, 1, 0, 0, 1]
[0, 0, 1, 1, 1, 1, 0, 0, 1]
[0, 1, 0, 0, 0, 1, 1, 1, 0]
[1, 0, 1, 1, 0, 1, 1, 0, 1]
[0, 0, 0, 0, 1, 0, 0, 0, 0]
[1, 0, 0, 1, 0, 1, 1, 0, 0]
[0, 0, 1, 1, 0, 0, 0, 0, 1]
[1, 0, 1, 1, 1, 0, 0, 1, 0]
[0, 0, 0, 0, 0, 0, 1, 0, 0]
请输入迷宫的大小:15
迷宫为:
[0, 1, 1, 1, 1, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0]
[0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0]
[0, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 1, 1, 0, 0]
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0]
[0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 0, 0]
[1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0]
[1, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 1, 0, 0]
[1, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0]
[1, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1]
[0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0]
[0, 0, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 1, 0]
[0, 0, 0, 0, 1, 0, 1, 0, 1, 1, 0, 1, 0, 1, 0]
[0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0]

仅展示部分结果,完整测试数据在"附件1"中。

4.2 深度遍历迷宫

参数

输入:

point------现在所在的位置

输出:

步骤

步骤说明:
判断现在的位置是否在终点
如果在终点:
将本路径添加到correct_road,删除最后一个位置,结束
否则:
向下一个位置探索,判断下一个位置是否能走
如果能走:
将下一个点添加到路径
Go(下一个点)
否则:
向下一个方向探索直到没有方向
在路径中删除现在的位置,结束

流程图:

代码:

def go(self, point):
    x, y = point
    if x == self.n - 1 and y == self.n - 1:
        self.correct_road.append(self.road.copy())
        del self.road[-1]
        return
    direction = [DIRECTION.DOWN.value, DIRECTION.RIGHT.value, DIRECTION.LEFT.value, DIRECTION.UP.value]
    self.maze[x][y] = 1
    for i in range(4):
        point = Point(x + direction[i][0], y + direction[i][1])
        x_new, y_new = point.point()
        if x_new < 0 or y_new < 0 or x_new >= self.n or y_new >= self.n:
            continue
        if self.maze[x_new][y_new] == 0:
            self.road.append(point.point())
            self.go(point.point())
    self.maze[x][y] = 0
    del self.road[-1]

4.3 输出迷宫路径

参数

输入:无

输出:无

步骤

  • 输出路径的数量
  • 挨个输出路径

<img src="http://akavjht.top/image/0022/image5.png"测试

  • 测试点1:1-10: 随机抽取10个

  • 测试点2:-100-100:随机抽取10个

  • 测试点3:-1000-1000:随机抽取10个

结果

请输入迷宫的大小:10
迷宫为:
[0, 1, 1, 0, 0, 1, 1, 0, 0, 0]
[0, 0, 0, 0, 1, 0, 0, 0, 1, 1]
[1, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[1, 1, 0, 0, 1, 1, 0, 1, 0, 1]
[1, 1, 1, 1, 0, 1, 0, 0, 1, 0]
[1, 0, 0, 1, 1, 0, 1, 0, 1, 1]
[0, 0, 1, 0, 0, 0, 1, 0, 1, 0]
[0, 0, 1, 1, 0, 0, 0, 0, 0, 0]
[1, 0, 0, 0, 0, 1, 0, 0, 0, 0]
[1, 0, 0, 0, 0, 0, 0, 0, 1, 0]
迷宫有0条路径

迷宫为:
[0, 0, 0, 1, 1]
[0, 0, 1, 0, 1]
[0, 1, 0, 1, 0]
[0, 0, 1, 0, 1]
[1, 0, 0, 0, 0]
迷宫有2条路径
[0, 0]  [0, 1]  [1, 1]  [1, 0]  [2, 0]  [3, 0]  [3, 1]  [4, 1]  [4, 2]  [4, 3]  [4, 4]  
[0, 0]  [1, 0]  [2, 0]  [3, 0]  [3, 1]  [4, 1]  [4, 2]  [4, 3]  [4, 4]  

请输入迷宫的大小:7
迷宫为:
[0, 0, 1, 0, 0, 0, 0]
[1, 0, 0, 0, 0, 1, 1]
[0, 0, 0, 1, 1, 0, 1]
[1, 0, 0, 0, 0, 1, 0]
[0, 0, 0, 0, 0, 1, 0]
[0, 0, 1, 0, 1, 1, 0]
[1, 0, 0, 0, 1, 0, 0]
迷宫有28条路径
[0, 0]  [0, 1]  [1, 1]  [1, 2]  [2, 2]  [3, 2]  [3, 3]  [3, 4]  [4, 4]  
[0, 0]  [0, 1]  [1, 1]  [1, 2]  [2, 2]  [3, 2]  [3, 3]  [4, 3]  [4, 4]  
[0, 0]  [0, 1]  [1, 1]  [1, 2]  [2, 2]  [3, 2]  [4, 2]  [4, 3]  [4, 4]  
[0, 0]  [0, 1]  [1, 1]  [1, 2]  [2, 2]  [3, 2]  [4, 2]  [4, 3]  [3, 3]  [3, 4]  [4, 4]  
[0, 0]  [0, 1]  [1, 1]  [1, 2]  [2, 2]  [3, 2]  [3, 1]  [4, 1]  [4, 2]  [4, 3]  [4, 4]  
[0, 0]  [0, 1]  [1, 1]  [1, 2]  [2, 2]  [3, 2]  [3, 1]  [4, 1]  [4, 2]  [4, 3]  [3, 3]  [3, 4]  [4, 4]  
[0, 0]  [0, 1]  [1, 1]  [1, 2]  [2, 2]  [2, 1]  [3, 1]  [3, 2]  [3, 3]  [3, 4]  [4, 4]  
[0, 0]  [0, 1]  [1, 1]  [1, 2]  [2, 2]  [2, 1]  [3, 1]  [3, 2]  [3, 3]  [4, 3]  [4, 4]  
[0, 0]  [0, 1]  [1, 1]  [1, 2]  [2, 2]  [2, 1]  [3, 1]  [3, 2]  [4, 2]  [4, 3]  [4, 4]  
[0, 0]  [0, 1]  [1, 1]  [1, 2]  [2, 2]  [2, 1]  [3, 1]  [3, 2]  [4, 2]  [4, 3]  [3, 3]  [3, 4]  [4, 4]  
[0, 0]  [0, 1]  [1, 1]  [1, 2]  [2, 2]  [2, 1]  [3, 1]  [4, 1]  [4, 2]  [4, 3]  [4, 4]  
[0, 0]  [0, 1]  [1, 1]  [1, 2]  [2, 2]  [2, 1]  [3, 1]  [4, 1]  [4, 2]  [4, 3]  [3, 3]  [3, 4]  [4, 4]  
[0, 0]  [0, 1]  [1, 1]  [1, 2]  [2, 2]  [2, 1]  [3, 1]  [4, 1]  [4, 2]  [3, 2]  [3, 3]  [3, 4]  [4, 4]  
[0, 0]  [0, 1]  [1, 1]  [1, 2]  [2, 2]  [2, 1]  [3, 1]  [4, 1]  [4, 2]  [3, 2]  [3, 3]  [4, 3]  [4, 4]  
[0, 0]  [0, 1]  [1, 1]  [2, 1]  [2, 2]  [3, 2]  [3, 3]  [3, 4]  [4, 4]  
[0, 0]  [0, 1]  [1, 1]  [2, 1]  [2, 2]  [3, 2]  [3, 3]  [4, 3]  [4, 4]  
[0, 0]  [0, 1]  [1, 1]  [2, 1]  [2, 2]  [3, 2]  [4, 2]  [4, 3]  [4, 4]  
[0, 0]  [0, 1]  [1, 1]  [2, 1]  [2, 2]  [3, 2]  [4, 2]  [4, 3]  [3, 3]  [3, 4]  [4, 4]  
[0, 0]  [0, 1]  [1, 1]  [2, 1]  [2, 2]  [3, 2]  [3, 1]  [4, 1]  [4, 2]  [4, 3]  [4, 4]  
[0, 0]  [0, 1]  [1, 1]  [2, 1]  [2, 2]  [3, 2]  [3, 1]  [4, 1]  [4, 2]  [4, 3]  [3, 3]  [3, 4]  [4, 4]  
[0, 0]  [0, 1]  [1, 1]  [2, 1]  [3, 1]  [3, 2]  [3, 3]  [3, 4]  [4, 4]  
[0, 0]  [0, 1]  [1, 1]  [2, 1]  [3, 1]  [3, 2]  [3, 3]  [4, 3]  [4, 4]  
[0, 0]  [0, 1]  [1, 1]  [2, 1]  [3, 1]  [3, 2]  [4, 2]  [4, 3]  [4, 4]  
[0, 0]  [0, 1]  [1, 1]  [2, 1]  [3, 1]  [3, 2]  [4, 2]  [4, 3]  [3, 3]  [3, 4]  [4, 4]  
[0, 0]  [0, 1]  [1, 1]  [2, 1]  [3, 1]  [4, 1]  [4, 2]  [4, 3]  [4, 4]  
[0, 0]  [0, 1]  [1, 1]  [2, 1]  [3, 1]  [4, 1]  [4, 2]  [4, 3]  [3, 3]  [3, 4]  [4, 4]  
[0, 0]  [0, 1]  [1, 1]  [2, 1]  [3, 1]  [4, 1]  [4, 2]  [3, 2]  [3, 3]  [3, 4]  [4, 4]  
[0, 0]  [0, 1]  [1, 1]  [2, 1]  [3, 1]  [4, 1]  [4, 2]  [3, 2]  [3, 3]  [4, 3]  [4, 4]  

迷宫为:
[0, 1, 0, 1, 0]
[1, 0, 0, 1, 0]
[1, 0, 0, 0, 0]
[0, 1, 0, 0, 0]
[1, 0, 0, 0, 0]
迷宫有0条路径

仅展示部分结果,完整测试数据在"附件1"中。

4.4 改良

问题

经过测试发现,迷宫的探索结果倾向于0条,因为迷宫的构成是随机获取0和1。

解决方法

对生成迷宫的函数进行改进,对迷宫的每个位置按照0.7:0.3的概率生成0和1。

将0的概率作为输入,所以0.7这个数值是可以改变的。

4.5 时间复杂度

4是4个方向,n×n是迷宫的规模

  • 最坏情况下:O(n2)

O(4(n2-1)) :除了终点,每个点在四个方向都探索一遍

  • 最好情况O(1)

O(4):在(0,0)四个方向都没办法走

  • 所以算法的时间复杂度为O(n2

200次迷宫探索时间图

4.6 空间复杂度

深度搜索算法是一个递归算法,需要借助一个递归工作栈,所以的空间复杂度是O(n2)

五、附录

迷宫探索

import numpy as np
from enum import Enum
import copy


class DIRECTION(Enum):
    UP = [0, -1]
    DOWN = [0, 1]
    LEFT = [-1, 0]
    RIGHT = [1, 0]


class Point():
    def __init__(self, x, y):
        self.x = x
        self.y = y

    def point(self):
        return [self.x, self.y]


class Maze():
    def __init__(self):
        self.start = Point(0, 0)
        self.maze = []
        self.n = 5
        self.road = []
        self.correct_road = []

    def get_maze(self, n):
        self.maze = np.random.randint(0, 2, (n, n))
        self.maze[0][0] = self.maze[n - 1][n - 1] = 0
        print("迷宫为:")
        for i in self.maze:
            print(i)

    def get_maze_prob(self, n, prob):
        for i in range(n):
            line = []
            for j in range(n):
                line.append(np.random.choice([0, 1], p=[prob, 1 - prob]))
            self.maze.append(line)
        self.maze[0][0] = self.maze[n - 1][n - 1] = 0
        print("迷宫为:")
        for i in self.maze:
            print(i)

    def print(self):
        print("迷宫有%d条路径" % len(self.correct_road))
        for i in self.correct_road:
            for j in i:
                print(j, " ", end="")
            print()

    def go(self, point):
        x, y = point
        if x == self.n - 1 and y == self.n - 1:
            self.correct_road.append(self.road.copy())
            del self.road[-1]
            return
        direction = [DIRECTION.DOWN.value, DIRECTION.RIGHT.value, DIRECTION.LEFT.value, DIRECTION.UP.value]
        self.maze[x][y] = 1
        for i in range(4):
            point = Point(x + direction[i][0], y + direction[i][1])
            x_new, y_new = point.point()
            if x_new < 0 or y_new < 0 or x_new >= self.n or y_new >= self.n:
                continue
            if self.maze[x_new][y_new] == 0:
                self.road.append(point.point())
                self.go(point.point())
        self.maze[x][y] = 0
        del self.road[-1]

    def main(self, n):
        self.get_maze_prob(n, 0.7)
        self.road.append(self.start.point())
        self.go(self.start.point())
        self.print()


if __name__ == "__main__":
    while True:
        n = int(input("请输入迷宫的大小:"))
        if n <= 0:
            print("请重新输入")
        else:
            break
    Maze().main(n)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值