7-4 迷宫-广度策略

7-4 迷宫-广度策略

分数 10

全屏浏览

切换布局

作者 张瑞霞

单位 桂林电子科技大学

一个陷入迷宫的老鼠如何找到出口的问题。老鼠希望系统性地尝试所有的路径之后走出迷宫。如果它到达一个死胡同,将原路返回到上一个位置,尝试新的路径。在每个位置上老鼠可以向八个方向运动,顺序是从正东开始按照顺时针进行。无论离出口多远,它总是按照这样的顺序尝试,当到达一个死胡同之后,老鼠将进行“回溯”。迷宫只有一个入口,一个出口,设计程序要求输出迷宫的一条通路。迷宫采用二维存储结构表示,1表示障碍,0表示通路;要求如下: 1、实现队列的相关操作; 2、利用队列进行广度策略搜索算法输出路径;

输入格式:

输入包括三部分: 第一个输入是迷宫大小;第二个输入是迷宫的状态;第三个输入是入口和出口位置

输出格式:

反向输出探索的路径,注意包括入口和出口位置。每个位置之间用分号;分隔。

输入样例:

9
1 1 1 1 1 1 1 1 1
1 0 0 1 1 0 1 1 1
1 1 0 0 0 0 0 0 1
1 0 1 0 0 1 1 1 1
1 0 1 1 1 0 0 1 1
1 1 0 0 1 0 0 0 1
1 0 1 1 0 0 0 1 1
1 1 1 1 1 1 1 0 1
1 1 1 1 1 1 1 1 1
1 1 7 7

输出样例:

7 7;6 6;5 6;4 5;3 4;2 3;1 2;1 1;

代码长度限制

16 KB

时间限制

400 ms

内存限制

64 MB

栈限制

8192 KB

这道迷宫问题的解题思路如下:

 一、问题分析
核心要求:
 1. 使用DFS(深度优先搜索)找到从入口到出口的路径
 2. 老鼠可以向八个方向移动(从正东开始顺时针)
 3. 需要记录并反向输出最短路径
二、数据结构设计

# 1. 迷宫表示
a = [[0] * 13 for _ in range(13)]    # 存储迷宫地图(0表示通路,1表示墙)
vis = [[0] * 13 for _ in range(13)]  # 记录已访问位置

# 2. 路径存储
class Point:
    def __init__(self, fx=0, fy=0):
        self.fx = fx
        self.fy = fy
path = [Point() for _ in range(100)]      # 当前路径
short_path = [Point() for _ in range(100)] # 最短路径

# 3. 方向数组(八个方向,从正东开始顺时针)
mov = [(0,1), (1,1), (1,0), (1,-1), (0,-1), (-1,-1), (-1,0), (-1,1)]

三、DFS算法实现

def dfs(x, y, step):
    # 1. 到达终点时的处理
    if x == end_x and y == end_y:
        if step < mn:  # 找到更短路径
            mn = step
            # 保存当前路径
            for i in range(step):
                short_path[i] = path[i]
        return

    # 2. 按顺序尝试八个方向
    for i in range(8):
        nx = x + mov[i][0]
        ny = y + mov[i][1]
        
        # 3. 检查新位置是否有效
        if nx < 1 or nx > n or ny < 1 or ny > n:
            continue
            
        # 4. 如果是未访问的通路
        if vis[nx][ny] == 0 and a[nx][ny] == 0:
            # 标记访问
            vis[nx][ny] = 1
            # 记录路径
            path[step].fx = nx
            path[step].fy = ny
            # 继续搜索
            dfs(nx, ny, step + 1)
            # 回溯:取消标记
            vis[nx][ny] = 0

四、算法步骤
1. 初始化:
   (1)读入迷宫大小和地图
   (2)读入起点和终点坐标
   (3)初始化访问数组和路径数组

2. 深度优先搜索:
   (1)从起点开始,按照八个方向顺序探索
   (2) 每到达一个新位置,记录在路径中
   (3)如果到达终点,更新最短路径
   (4)使用回溯法返回尝试其他路径

3. 路径记录:
   (1)使用 `path` 数组记录当前探索路径
   (2)使用 `short_path` 数组记录最短路径
   (3)每找到一条更短的路径就更新 `short_path`

4. 输出结果:
   (1)反向输出最短路径(从终点到起点)
   (2)每个坐标之间用分号分隔

五、最终完整代码

# 全局变量
mn = 100000  # 最小步数
n = 0        # 迷宫大小
start_x = start_y = 0  # 起始位置
end_x = end_y = 0      # 结束位置

# 迷宫数组和访问标记数组
a = [[0] * 13 for _ in range(13)]
vis = [[0] * 13 for _ in range(13)]

# 路径存储
class Point:
    def __init__(self, fx=0, fy=0):
        self.fx = fx
        self.fy = fy

path = [Point() for _ in range(100)]
short_path = [Point() for _ in range(100)]

# 八个方向:东、东南、南、西南、西、西北、北、东北
mov = [(0,1), (1,1), (1,0), (1,-1), (0,-1), (-1,-1), (-1,0), (-1,1)]

def dfs(x, y, step):
    global mn
    if x == end_x and y == end_y:
        if step < mn:
            mn = step
            for i in range(step):
                short_path[i].fx = path[i].fx
                short_path[i].fy = path[i].fy
        return

    for i in range(8):
        nx = x + mov[i][0]
        ny = y + mov[i][1]
        if nx < 1 or nx > n or ny < 1 or ny > n:
            continue
        if vis[nx][ny] == 0 and a[nx][ny] == 0:
            vis[nx][ny] = 1
            path[step].fx = nx
            path[step].fy = ny
            dfs(nx, ny, step + 1)  # 回溯
            vis[nx][ny] = 0

def main():
    global n, start_x, start_y, end_x, end_y

    # 输入迷宫大小
    n = int(input())
    
    # 输入迷宫状态
    for i in range(n):
        row = list(map(int, input().split()))
        for j in range(n):
            a[i][j] = row[j]
    
    # 输入起点和终点坐标(在同一行)
    coords = list(map(int, input().split()))
    start_x, start_y = coords[0], coords[1]
    end_x, end_y = coords[2], coords[3]
    
    # 标记起点已访问
    vis[start_x][start_y] = 1
    
    # DFS搜索路径
    dfs(start_x, start_y, 1)
    
    # 输出路径
    for i in range(mn-1, 0, -1):
        print(f"{short_path[i].fx} {short_path[i].fy};", end="")
    print(f"{start_x} {start_y};", end="")

if __name__ == "__main__":
    main()

六、运行截图

 

### 递归实现统计二叉树中右孩子节点数量 要通过递归方法统计二叉树中的右孩子节点数量,核心思路是对每个节点进行判断:如果当前节点存在右子节点,则将其计入总数;随后分别递归处理其左子树和右子树。 以下是具体的实现逻辑: #### 方法描述 定义一个函数 `getRightChildCount` 接收二叉树的根节点作为参数。对于每一个节点: - 如果该节点为空,则返回 0。 - 如果该节点有右子节点,则计数加一,并继续递归计算其左子树和右子树中的右孩子节点数量。 - 将左右子树的结果相加并返回最终值。 此过程遵循递归的基本原则,即分解问题为更小的部分逐一解决[^1]。 #### 实现代码 以下是一个 C++ 的代码示例用于演示上述逻辑: ```cpp struct TreeNode { int val; TreeNode* left; TreeNode* right; TreeNode(int x) : val(x), left(nullptr), right(nullptr) {} }; int getRightChildCount(TreeNode* root) { if (root == nullptr) { return 0; // 基本情况:空节点不贡献任何右孩子节点 } int count = 0; if (root->right != nullptr) { count += 1; // 当前节点有一个右孩子节点 } // 对左子树和右子树递归调用 count += getRightChildCount(root->left); count += getRightChildCount(root->right); return count; } ``` 这段代码实现了对整个二叉树的遍历,并仅当遇到某个节点具有右子节点时才增加计数值[^2]。 #### 复杂度分析 时间复杂度为 O(n),其中 n 是二叉树中的总节点数。这是因为每个节点都会被访问一次以决定它是否有右孩子节点[^3]。空间复杂度取决于递归栈的最大深度,在最坏情况下(退化成链表),这将是 O(h),h 表示树的高度。 --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值