搜索策略-DFS,BFS,爬山法,分支界限法

本文详细介绍了几种搜索策略,包括Prim和Krusal两种最小生成树算法,广度优先搜索(BFS)、深度优先搜索(DFS)、爬山法、最佳优先搜索和分支界限法。这些方法在图论和搜索问题中广泛应用,涉及到数据结构如队列、栈和堆,以及优化问题的解决。A*算法作为一种高效搜索策略,结合了最佳优先搜索的特点,通过估价函数f(n)指导搜索方向。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

最小生成树

Prim

基本思路:将点的集合分为C 和 V-C ,分别为访问过的。

Krusal

将每个顶点维护成单顶点连通分量 C(v1),C(vn)
1. 先将边进行排序
2. 每次加入权值最小的边,如果两个节点在不同的连通分量,则加入,否则丢弃 最好的实现方式是使用并查集,时间复杂度为 O(|E|log|E|) 使用链表,算法复杂度 O(|V|3)

广度优先

思想:逐层访问搜索树中的节点,用到了队列Q。

访问队列Q的第一个节点:

  1. 如果绑定函数 B(x) 可能存在可行解,则将它的所有孩子节点压入队列Q末尾;
  2. 如果是可行解,如果是目标节点,则输出x对应的解
  3. 如果不可能存在可行解,重复操作。

当队列Q为空时,算法结束。

深度优先

思想: 尽可能深的访问树的节点,优先扩展最近访问过的节点,用到了栈S。

访问栈顶S的第一个元素:

  1. 如果绑定函数 B(x) 可能存在可行解,则将它的所有孩子节点压入栈S;
  2. 如果是可行解,如果是目标节点,则输出x对应的解
  3. 如果不可能存在可行解,重复操作。

当栈S为空时,算法结束。

爬山法

定义了隐式约束P(x),可以判断X是否为目标节点,还可以衡量x与目标节点的距离。

在深度优先的策略进行修改,当扩展一个节点X时,如果不是目标节点,则根据隐式函数P()的值从大到小将x的每一个节点压入栈。 局部贪心

访问栈顶S的第一个元素:

  1. 如果绑定函数 B(x) 可能存在可行解,根据隐式函数P()的值从大到小将x的每一个节点压入栈;
  2. 如果是可行解,如果是目标节点,则输出x对应的解
  3. 如果不可能存在可行解,重复操作。

当栈S为空时,算法结束。

最佳优先

思想: 结合了深度优先和广度优先的简单搜索策略,其实也是爬山法由局部扩展到全局。 最佳优先用到了堆管理扩展节点。

访问堆顶Q的第一个元素:

  1. 如果绑定函数 B(x) 可能存在可行解,根则将所有孩子节点插入堆;
  2. 如果是可行解,如果是目标节点,则输出x对应的解
  3. 如果不可能存在可行解,重复操作。

当栈Q为空时,算法结束。

分支界限法

与前面四种策略不同的是,分支界限法可以用于求解优化问题。 特点:利用已经得到的可行解,剪除不能得到优化解的分支

两个要素:

  1. 产生可行解的策略,可以用前面的深度优先,爬山法,最佳优先。
  2. 剪除分支的策略: 判断以x为根节点可行解代价是否大于已知可行解的最小代价。绑定函数,具体判断。

应用

代价矩阵: 为了提高分界法的剪枝能力,可以用代价矩阵的变换得到一个所有可行解的代价下界。

行列进行变化: 使得每一行每一列至少存在一个0的元素。最小代价为减去的值。

代价上升: 得到代价矩阵之后,选择一个0元素,对可行解空间进行划分,右子树(不包含0)代价下界增加最大,每个分支的代价矩阵也发生变化。

A*算法

求解最小化或者最大化问题。

g(n) 为搜索树根节点到节点n的精确代价。

h(n) 为节点n到目标节点的最小代价。

f(n) 为从根节点到目标节点的最小代价。

f(n) 为 f(n) 的估计值, f(n)<=f(n)

其实A*算法有点类似于最佳优先策略

访问栈顶S的第一个元素:

  1. 如果绑定函数 B(x) 可能存在可行解,根据总代价值f(x)从小到大将x的每一个节点压入栈;
  2. 如果是可行解,如果是目标节点,则输出x对应的解
  3. 如果不可能存在可行解,重复操作。

当栈S为空时,算法结束。

剪枝: 找到的f(n) > 已知可行解的cost

### 关于0-1背包问题的分支界限法BFS实现) #### 背景介绍 分支界限法是一种用于解决组合优化问题的有效方法。对于0-1背包问题,目标是在不超过容量的情况下最大化物品的价值。通过将决策变量从离散域扩展到连续域来计算上下界是一个常见的策略[^1]。 #### BFS 实现中的核心概念 在基于广度优先搜索 (BFS) 的分支界限法中,节点表示可能的选择状态集合。为了减少不必要的探索并提高效率,可以利用边界条件剪枝。具体来说: - **上界的估计**:可以通过放松约束条件,即将物品重量视为可分割的情况下的最优解作为当前子树的最大可能值。 - **可行性判断**:如果某个路径上的累积重量超过了给定的容量,则该路径被丢弃。 以下是具体的算法描述以及其实现方式。 #### 算法设计 ##### 数据结构准备 定义一个队列存储待处理的状态节点,每个节点包含如下信息: - 当前已选物品列表; - 已使用的总重量; - 总价值; - 剩余未考虑物品索引; ##### 主要逻辑流程 初始化时把根节点加入队列,并按照层次遍历的方式依次取出节点进行分析直到找到最佳答案为止。 ```python from collections import deque def knapsack_bfs(weights, values, capacity): n = len(values) class Node: def __init__(self, level, profit, weight, items): self.level = level # 下一待评估物品编号 self.profit = profit # 当前利润 self.weight = weight # 当前装载量 self.items = items # 所含项目清单 max_profit = 0 # 记录最大收益 queue = deque() # 初始化队列 root = Node(-1, 0, 0, []) # 创建初始节点 queue.append(root) while queue: node = queue.popleft() if node.weight <= capacity and node.profit > max_profit: max_profit = node.profit next_level = node.level + 1 if next_level < n: # 不取下一个物品的新节点 new_node_no_take = Node(next_level, node.profit, node.weight, list(node.items)) queue.append(new_node_no_take) if weights[next_level] + node.weight <= capacity: # 取下一个物品的新节点 new_items_with_next = list(node.items) new_items_with_next.append(next_level) new_node_take = Node(next_level, node.profit + values[next_level], node.weight + weights[next_level], new_items_with_next) queue.append(new_node_take) return max_profit ``` 上述代码片段展示了如何使用广度优先搜索配合分支限界技术求解0-1背包问题。 #### 结论 这种方法能够有效地缩小搜索空间从而提升性能表现。然而需要注意的是,在实际应用过程中还需要进一步优化以应对更大规模的数据集挑战。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值