伯克利吃豆人编程作业——深度优先搜索

本文章内容作为课上内容归纳和个人编程学习的记录,有关代码来自编程作业文件和B站图文专栏 https://www.bilibili.com/opus/410980451283542691?spm_id_from=333.1007.0.0
应用背景:单状态问题

  • 初始状态
  • 可能行动
  • 转移函数
  • 目标测试:判断给定状态是不是目标状态
  • 路径耗散:为每条路径赋一个耗散值
    解就是从初始状态导向目标状态的行动序列

深度优先搜索

一、深度优先策略的定义

在搜索过程中,优先扩展最新产生的(即最深的)节点,深度相等的节点顺序任意,符合上述特征的搜索被称为深度优先搜索。这种后进先出(Last In First Out,LIFO)的特点与栈一致,因此在编程实现中使用栈来放置待扩展节点。

二、题目信息

  • 已提供的函数
    getStartState(self):返回搜索问题的初始状态,状态通常是坐标形式(x,y)
    isGoalState(self, state):判断当前状态state是否为目标状态,返回布尔值
    getSuccessors(self, state):对于状态state,返回一个三元组(后续状态,行动,代价),,后续状态通常为坐标形式(x,y)
  • 待编辑函数
    depFirstSearch(problem)

三、代码实现

点击查看代码
def depthFirstSearch(problem):
    """
    // ... 原有注释保持不变 ...
    """
    # 初始化已访问集合和栈
    exploredNodes = set()
    fringe = util.Stack()
    startState = problem.getStartState()

    # 如果起始状态就是目标,直接返回
    if problem.isGoalState(startState):
        return []

    # 修改初始路径的存储格式,不再存储'Start'动作
    fringe.push([(startState, None, 0)])

    while not fringe.isEmpty():
        currentPath = fringe.pop()#pop函数的作用:弹出栈顶并作为函数返回值,等效于在栈中去除该节点
        currentState = currentPath[-1][0]#currentPath是

        # 如果当前状态已经访问过,继续下一个
        if currentState in exploredNodes:
            continue

        # 标记当前状态为已访问
        exploredNodes.add(currentState)

        # 如果找到目标,返回动作序列
        if problem.isGoalState(currentState):
            # 只返回实际的移动动作(排除None)
            return [x[1] for x in currentPath if x[1] is not None]

        # 获取后继状态并加入栈中
        for successor in problem.getSuccessors(currentState):
            if successor[0] not in exploredNodes:
                nextPath = currentPath[:]
                nextPath.append(successor)
                fringe.push(nextPath)

    return []#只有在没有找到目标节点才会运行到这里
posted @ 2024-11-26 21:04  东张西望过马路  阅读(39)  评论(0)    收藏  举报