算法入门篇(九)之 搜索技术

目录

一、二分搜索

1.整数上的二分

算法步骤

代码实现(Python)

复杂度分析

示例

2.实数上的二分

应用场景

算法步骤

代码实现(Python示例)

复杂度分析

示例说明

3.POJ3258、POJ3104、POJ1759、POJ1064

1. POJ3258 - River Hopscotch

题目简介

解题思路

代码示例(Python)

2. POJ3104 - Drying

题目简介

解题思路

代码示例(Python)

3. POJ1759 - Climbing the Hill

题目简介

解题思路

代码示例(Python)

4. POJ1064 - Cable Master

题目简介

解题思路

代码示例(Python)

二、深度优先搜索

1.回潮法、子集树、m叉树、排列树

1. 回潮法(Backtracking)

概念

应用场景

典型算法结构

2. 子集树(Subset Tree)

概念

特点

应用场景

例子

3. m 叉树(m-ary Tree)

概念

特点

常见类型

应用场景

4. 排列树(Permutation Tree)

概念

特点

应用场景

例子

5.总结

2.DFS 的特点

3.DFS 算法的应用

4.DFS 的实现

1. 递归实现

2. 使用栈的迭代实现

5.示例

6.复杂度分析

7.总结

三、广度优先搜索

BFS 的特点

BFS 的应用

BFS 的实现

BFS 的复杂度分析

应用场景

总结

四、启发式搜索

核心思想

常见算法

算法示例(A* 算法)

A* 算法步骤

代码实现(Python 示例)

A* 算法的特点

应用场景

总结


一、二分搜索

1.整数上的二分

算法步骤

  1. 初始化:设定两个指针,left 指向数组的起始位置,right 指向数组的结束位置。

  2. 循环查找

    • 计算中间位置 mid = left + (right - left) // 2
    • 如果 nums[mid] = = target,则找到目标元素,返回其下标。
    • 如果 nums[mid] < target,说明目标元素在 mid 右侧,则更新 left = mid + 1
    • 如果 nums[mid] > target,说明目标元素在 mid 左侧,则更新 right = mid - 1
  3. 终止条件:当 left > right 时,查找结束。如果找不到目标元素,通常返回 -1 或其他标志值。

代码实现(Python)

def binary_search(nums, target):
    left, right = 0, len(nums) - 1
    
    while left <= right:
        mid = left + (right - left) // 2
        
        if nums[mid] == target:
            return mid
        elif nums[mid] < target:
            left = mid + 1
        else:
            right = mid - 1
    
    return -1  # 表示未找到目标元素

复杂度分析

  • 时间复杂度:O(log n),每次查找范围缩小一半。
  • 空间复杂度:O(1),只使用了常数级别的额外空间。

示例

nums = [1, 2, 4, 5, 7, 9, 12]
target = 5
result = binary_search(nums, target)
print(result)  # 输出: 3

2.实数上的二分

在实数域上进行二分查找,通常用于求解函数的根、极值、或其他需要精确求解的数值问题。与离散整数上的二分查找不同,实数上的二分查找需要在一定的精度范围内找到一个解,而不是精确的索引。

应用场景

  • 求解方程的根,如 f(x)=0
  • 找到函数的极值点
  • 找到某个条件下的最优解

算法步骤

  1. 初始化:确定实数范围的两个端点 leftright,它们之间包含目标值或解。

  2. 设定精度:由于实数是连续的,设定一个精度值 epsilon,当区间范围小于 epsilon 时,认为找到了解。

  3. 循环查找

    • 计算中间点 mid = (left + right) / 2
    • 根据问题的性质,判断中间点处的值与目标值或目标条件的关系,选择下一步缩小的区间:
      • 如果 f(mid) 满足条件(例如足够接近 0),则认为找到了解,退出循环。
      • 如果 f(mid) 不满足条件,则根据 f(mid)f(left)f(right) 的关系,确定下一个查找的区间。
      • 更新区间的左端点或右端点。
  4. 终止条件:当 right - left < epsilon 时,查找结束。返回 mid 作为结果。

代码实现(Python示例)

以下是求函数 f(x)=x²−2的根,也就是求√2的近似值。

def binary_search_real(f, left, right, epsilon=1e-7):
    while right - left > epsilon:
        mid = (left + right) / 2
        if f(mid) == 0:  # 精确找到根
            return mid
        elif f(mid) < 0:  # 根在右半边
            left = mid
        else:  # 根在左半边
            right = mid
    return (left + right) / 2  # 返回近似解

# 求解 x^2 - 2 = 0 的根,即 √2
result = binary_search_real(lambda x: x**2 - 2, 1, 2)
print(result)  # 输出接近 √2 的值

复杂度分析

  • 时间复杂度:O(log(1/epsilon)),每次查找将区间缩小一半,直至满足精度要求。
  • 空间复杂度:O(1),只使用了常数级别的额外空间。

示例说明

  • 在这个例子中,我们通过二分查找来逼近​。假设我们知道 2\sqrt{2}2​ 位于区间 [1, 2],二分查找逐步缩小区间,直到找到一个足够接近的值。

  • 设置的 epsilon 决定了最终结果的精度。若需要更高的精度,可以设置更小的 epsilon

3.POJ3258、POJ3104、POJ1759、POJ1064

1. POJ3258 - River Hopscotch

题目简介

给定一条河流,河上有一些石头以及起点和终点。你可以移走最多 m 个石头,求移除后的石头之间的最小距离的最大值。

解题思路

这是一个典型的二分查找+贪心算法的问题。问题可以转化为:如何找到一个最大的最小距离,使得在移除最多 m 个石头的情况下,石头之间的最小距离仍然不小于该值。

具体步骤如下:

  1. 二分查找:最小距离的上下界可以通过石头间的最小间隔和最大间隔确定。
  2. 贪心判断:在每次二分的过程中,通过贪心算法计算在当前距离下是否可以满足条件。
代码示例(Python)
def can_place_stones(min_dist, stones, m):
    last_position = 0  # 起点
    remove_count = 0  # 已经移除的石头数量
    
    for i in range(1, len(stones)):
        if stones[i] - stones[last_position] < min_dist:
            remove_count += 1  # 移除这个石头
            if remove_count > m:
                return False
        else:
            last_position = i  # 更新最近的石头位置
    return True

def max_min_distance(stones, m):
    left, right = 0, stones[-1] - stones[0]
    
    while left <= right:
        mid = (left + right) // 2
        if can_place_stones(mid, stones, m):
            left = mid + 1  # 尝试更大的最小距离
        else:
            right = mid - 1  # 减小最小距离
    
    return right

# 输入:石头位置和可移除石头数
stones = [0, 2, 11, 14, 17, 21, 25]  # 示例输入
m = 2  # 可以移除的石头数
print(max_min_distance(stones, m))  # 输出最大最小距离

2. POJ3104 - Drying

题目简介

n 件衣服,每件衣服初始时都有一定的湿度。现在可以使用一种自然晾干方式,每单位时间衣服的湿度减少 1;也可以使用一种特殊晾干机,每单位时间可以使衣服的湿度减半。求使所有衣服干燥的最少时间。

解题思路

这也是一个典型的二分查找+贪心算法问题。我们可以通过二分搜索答案,即找到一个时间值 T,判断在该时间内能否将所有衣服晾干。

  1. 二分查找:我们假设一个最少时间 T,然后判断在该时间内是否能把所有衣服晾干。
  2. 贪心判断:对于每件衣服,如果自然晾干不能在 T 时间内完成,那么需要使用特殊晾干机,并计算需要使用多少次特殊晾干机才能使衣服干燥。
代码示例(Python)
def can_dry_all_clothes(T, clothes, k):
    extra_time = 0
    for wetness in clothes:
        if wetness > T:
            extra_time += (wetness - T + k - 2) // (k - 1)
            if extra_time > T:
                return False
    return True

def min_drying_time(clothes, k):
    left, right = 0, max(clothes)
    
    while left < right:
        mid = (left + right) // 2
        if can_dry_all_clothes(mid, clothes, k):
            right = mid  # 尝试更少的时间
        else:
            left = mid + 1  # 增加时间
    
    return left

# 输入:衣服湿度和晾干机效果
clothes = [10, 20, 30]  # 示例输入
k = 2  # 每次减半
print(min_drying_time(clothes, k))  # 输出最少晾干时间

3. POJ1759 - Climbing the Hill

题目简介

给定一个长度为 n 的数组,数组的第一个元素 a1 已知。你需要找出数组的第二个元素 a2,使得数组中的所有元素均为正数,并且最大值最小。

解题思路

这是一个二分查找模拟的问题。通过二分查找确定 a2 的最小值,然后依次推导后续元素,判断是否所有元素为正且满足要求。

代码示例(Python)
def is_valid_sequence(a1, a2, n):
    heights = [0] * n
    heights[0], heights[1] = a1, a2
    
    for i in range(2, n):
        heights[i] = 2 * heights[i - 1] - heights[i - 2]
        if heights[i] <= 0:
            return False
    
    return True

def find_minimum_maximum(n, a1):
    left, right = 0, 2 * a1
    
    while right - left > 1e-7:
        mid = (left + right) / 2
        if is_valid_sequence(a1, mid, n):
            right = mid
        else:
            left = mid
    
    return right

# 输入:数组长度和第一个元素
n = 5  # 示例输入
a1 = 10  # 第一个元素
print(find_minimum_maximum(n, a1))  # 输出最大最小值

4. POJ1064 - Cable Master

题目简介

给定 n 条电缆,需要将这些电缆切割成长度相同的若干段,使得至少能得到 k 段。求可以得到的电缆最大长度。

解题思路

这是典型的二分查找问题。可以通过二分搜索电缆的长度,找到最大值。

  1. 二分查找:在最大长度和最小长度之间搜索可以切割的最大长度。
  2. 贪心判断:对于每次二分确定的长度,判断是否能切割出 k 段。
代码示例(Python)
def can_cut_cables(length, cables, k):
    count = 0
    for cable in cables:
        count += cable // length
    return count >= k

def max_cable_length(cables, k):
    left, right = 0, max(cables)
    
    while right - left > 1e-7:
        mid = (left + right) / 2
        if can_cut_cables(mid, cables, k):
            left = mid  # 尝试更大的长度
        else:
            right = mid  # 减小长度
    
    return left

# 输入:电缆长度数组和目标段数
cables = [4, 7, 9]  # 示例输入
k = 5  # 需要得到的段数
print(max_cable_length(cables, k))  # 输出最大长度

二、深度优先搜索

深度优先搜索(Depth-First Search, DFS)是一种用于遍历或搜索图或树数据结构的算法。DFS 尽可能深地搜索树或图的分支,直到无法继续为止,然后回溯并继续探索其他分支。这种算法可以用来解决路径查找、连通性判断、拓扑排序等问题。

1.回潮法、子集树、m叉树、排列树

1. 回潮法(Backtracking)

概念

回潮法(又称为回溯法,Backtracking)是一种通过探索所有可能的解来找到问题的解法,适用于解决组合问题。其核心思想是在尝试解决问题时,逐步构建解,并在发现当前部分解无法扩展为有效解时,撤销该部分解(即“回溯”),然后尝试其他可能的路径。

应用场景
  • 组合问题:如求解排列、组合、子集。
  • 排列问题:如八皇后问题、数独问题。
  • 图搜索问题:如 Hamilton 回路、迷宫问题。
典型算法结构

回溯法可以用递归来实现。每次递归调用时,尝试扩展当前解,如果发现扩展后的解非法,则回溯。

def backtrack(solution):
    if solution is a complete solution:
        process(solution)
        return
    for option in possible_options:
        if option is valid:
            solution.add(option)
            backtrack(solution)
            solution.remove(option)  # 回溯

2. 子集树(Subset Tree)

概念

子集树是一种用于求解子集问题的搜索树,通常用于组合问题中。例如,给定一个集合,要求出所有可能的子集。每个节点表示是否包含集合中的某个元素。

特点
  • 二叉树结构:子集树通常是一棵二叉树,每个节点有两个子节点,分别表示包含或不包含某个元素。
  • 树的深度:如果集合的大小为 n,那么树的深度为 n,树的叶子节点数为 2^n
应用场景
  • 求子集:找到集合的所有子集。
  • 背包问题:通过子集树来求解背包问题的可行解。
例子

假设集合为 {a, b, c},子集树的部分结构如下:

               {}
          /         \
       {a}          {}
      /   \        /   \
   {a,b}  {a}   {b}    {}
   /  \   /  \   /  \   /  \
{a,b,c}... {a}...

3. m 叉树(m-ary Tree)

概念

m 叉树是一种树形结构,其中每个节点最多有 m 个子节点。m 叉树是一种广义的树结构,二叉树(m=2)是它的特例。m 叉树广泛应用于文件系统、数据库索引等场景。

特点
  • 节点:每个节点最多有 m 个子节点。
  • 递归结构:每个子树也是一棵 m 叉树。
常见类型
  • 完全 m 叉树:每个节点都有 m 个子节点,除最后一层的叶子节点外。
  • 平衡 m 叉树:所有叶子节点的深度相同或相差不大。
应用场景
  • B 树和 B+ 树:用于数据库和文件系统的索引。
  • 游戏 AI:搜索树用于决策(如 Minimax 算法)。

4. 排列树(Permutation Tree)

概念

排列树是一种用于生成集合中所有排列的搜索树。在排列树中,每个节点表示某个元素被放置在排列中的某个位置,搜索树的深度等于排列的长度。

特点
  • 深度优先遍历:通常通过深度优先遍历(DFS)来构建排列树,递归生成排列。
  • 剪枝:可以通过剪枝来减少不必要的排列生成,优化搜索效率。
应用场景
  • 全排列生成:列出集合中元素的所有排列。
  • 旅行商问题:通过排列树来生成所有路径,寻找最优路径。
例子

假设集合为 {a, b, c},其排列树结构如下:

               {}
         /     |     \
       a      b       c
      /  \    /  \    /  \
   ab   ac  ba   bc  ca   cb
   |    |   |    |   |    |
  abc  acb bac  bca cab  cba

5.总结

  • 回潮法:用于解决组合问题的通用方法,通过递归搜索并在失败时回溯。
  • 子集树:用于生成集合子集的二叉树结构。
  • m 叉树:通用的树结构,每个节点最多有 m 个子节点,广泛应用于数据库和文件系统。
  • 排列树:用于生成集合排列的搜索树结构,通常与深度优先搜索结合。

2.DFS 的特点

  • 递归/栈实现:DFS 可以通过递归或显式使用栈来实现。
  • 回溯:在探索完一条路径后,DFS 会回溯到上一个节点,继续探索未访问的路径。

3.DFS 算法的应用

  1. 路径查找:寻找从起点到终点的路径。
  2. 连通性检测:判断图是否连通,或找到连通分量。
  3. 拓扑排序:在有向无环图(DAG)中,确定节点的线性顺序。
  4. 迷宫求解:探索所有可能的路径,找到出口。

4.DFS 的实现

DFS 可以应用于,我们以图为例,假设图用邻接表表示。

1. 递归实现

def dfs(graph, node, visited):
    if node in visited:  # 如果节点已经访问过,返回
        return
    
    visited.add(node)  # 将节点标记为已访问
    print(node)  # 打印当前访问的节点(或进行其他操作)

    for neighbor in graph[node]:  # 访问当前节点的所有邻居
        dfs(graph, neighbor, visited)  # 对每个邻居递归调用 DFS

2. 使用栈的迭代实现

def dfs_iterative(graph, start):
    visited = set()  # 存储已访问节点
    stack = [start]  # 使用栈存储待访问节点
    
    while stack:
        node = stack.pop()  # 弹出栈顶元素
        
        if node not in visited:
            print(node)  # 打印当前访问的节点(或进行其他操作)
            visited.add(node)  # 将节点标记为已访问
            
            for neighbor in graph[node]:  # 将未访问的邻居加入栈
                if neighbor not in visited:
                    stack.append(neighbor)

5.示例

给定一个图,如下所示:

A -- B -- D
|    |
C    E

使用邻接表表示图:

graph = {
    'A': ['B', 'C'],
    'B': ['A', 'D', 'E'],
    'C': ['A'],
    'D': ['B'],
    'E': ['B']
}

执行 DFS:

visited = set()
dfs(graph, 'A', visited)

输出可能是:

A
B
D
E
C

或其他等效的顺序,具体取决于邻居的访问顺序。

6.复杂度分析

  • 时间复杂度:O(V + E),其中 V 是图中的节点数,E 是边数。DFS 会访问每个节点和每条边一次。
  • 空间复杂度:O(V),递归调用栈或显式栈需要保存当前路径中的节点,最坏情况下需要 O(V) 的空间。

7.总结

深度优先搜索是一种强大且灵活的图遍历算法,适用于多种问题场景。它的递归和迭代版本都有广泛的应用,尤其在图的遍历、路径搜索和连通性判断等方面表现出色。

三、广度优先搜索

广度优先搜索(Breadth-First Search, BFS)是一种用于遍历或搜索图或树数据结构的算法。与深度优先搜索不同,BFS 是从根节点开始,首先遍历其所有邻居节点,然后再遍历每个邻居的邻居节点,层层向外扩展,直到找到目标节点或遍历完所有节点。

BFS 的特点

  • 队列实现:BFS 通常使用队列来实现,队列用于存储待访问的节点。
  • 层次遍历:BFS 会逐层遍历图中的节点,先访问距离起点最近的节点,然后逐步扩展到更远的节点。
  • 最短路径:在无权图中,BFS 能够找到从起点到终点的最短路径,因为它按层次遍历,每层的距离都比前一层大一。

BFS 的应用

  1. 最短路径:在无权图中,BFS 可以找到从起点到终点的最短路径。
  2. 连通性检测:判断图是否连通,或找到连通分量。
  3. 遍历图的每一层:用于分层遍历或查找。
  4. 解决迷宫问题:在网格图中,寻找从起点到终点的最短路径。

BFS 的实现

假设图用邻接表表示,BFS 的基本实现如下:

from collections import deque

def bfs(graph, start):
    visited = set()  # 用于存储已访问的节点
    queue = deque([start])  # 初始化队列,起点入队
    
    while queue:
        node = queue.popleft()  # 从队列中取出第一个节点
        
        if node not in visited:
            print(node)  # 处理当前节点(例如打印节点)
            visited.add(node)  # 标记节点为已访问
            
            for neighbor in graph[node]:  # 遍历当前节点的邻居
                if neighbor not in visited:
                    queue.append(neighbor)  # 邻居节点入队

给定一个图,如下所示:

A -- B -- D
|    |
C    E

使用邻接表表示图:

graph = {
    'A': ['B', 'C'],
    'B': ['A', 'D', 'E'],
    'C': ['A'],
    'D': ['B'],
    'E': ['B']
}

执行 BFS:

bfs(graph, 'A')

输出可能是:

A
B
C
D
E

BFS 会按照层次遍历图的节点,先访问 A 的邻居 BC,然后访问 B 的邻居 DE

BFS 的复杂度分析

  • 时间复杂度:O(V + E),其中 V 是图中的节点数,E 是边数。BFS 会访问每个节点和每条边一次。
  • 空间复杂度:O(V),队列最多会包含每层的所有节点,因此需要 O(V) 的空间来存储这些节点。

应用场景

  1. 图的遍历:BFS 可以遍历图的所有节点,并在图中寻找某个特定节点或检查图的连通性。
  2. 最短路径问题:在无权图中,BFS 是寻找最短路径的有效算法。
  3. 拓扑排序:在某些情况下,BFS 可以用于计算拓扑排序(例如基于入度的 Kahn 算法)。
  4. 迷宫求解:在网格图中,BFS 可以用于找到从起点到终点的最短路径,适用于迷宫问题。

总结

广度优先搜索是一种基于层次遍历的算法,特别适合解决最短路径问题和连通性检测问题。它通过队列的方式进行节点管理,确保按层次顺序访问节点,因此在无权图中,BFS 可以找到最短路径,是一种非常重要且高效的图搜索算法。

四、启发式搜索

启发式搜索(Heuristic Search)是一种利用启发式信息(即对问题解空间的某种估计)来指导搜索过程的算法,常用于在复杂搜索空间中快速找到近似最优解。它通过优先搜索那些看起来更接近目标状态的节点,从而减少搜索空间,加速搜索过程。

核心思想

  • 启发函数:启发式搜索依赖于一个启发函数(Heuristic Function),该函数用于估计从当前状态到目标状态的成本或距离。启发函数通常用 h(n)h(n)h(n) 表示,其中 nnn 是当前节点。
  • 优先搜索:启发式搜索会优先探索启发函数值较小的节点,因为这些节点被认为离目标更近。

常见算法

  1. 贪心搜索(Greedy Search)

    • 只考虑启发函数 h(n),每次选择启发函数值最小的节点进行扩展。
    • 优点:相对简单,计算效率高。
    • 缺点:由于只考虑当前节点到目标节点的估计距离,容易陷入局部最优。
  2. A 算法*:

    • 结合实际代价和启发式估计,综合考虑从起点到当前节点的实际代价 g(n) 和从当前节点到目标的启发式估计 h(n),总的代价函数为 f(n)=g(n)+h(n)。
    • 优点:如果启发函数是一致的可接受的,A* 能保证找到最优解。
    • 缺点:计算开销较大,尤其在复杂的搜索空间中。
  3. IDA(Iterative Deepening A)算法**:

    • 结合深度优先搜索和 A* 算法的优点,采用迭代加深的方式,在每一层搜索中使用启发式估计 f(n)=g(n)+h(n) 来限制搜索深度。
    • 优点:在大规模搜索问题上节省内存,适合用于内存受限的场景。
    • 缺点:需要多次重复搜索,可能会增加计算时间。

算法示例(A* 算法)

A* 算法是启发式搜索的经典代表,它通过结合实际代价和启发式估计来寻找最优路径。

A* 算法步骤
  1. 初始化:将起点加入开放列表(Open List),并将其代价 f(n)初始化为 f(n)=g(n)+h(n),其中 g(n)=0,h(n)是启发式估计。
  2. 选择节点:从开放列表中选择代价最小的节点作为当前节点进行扩展。
  3. 扩展节点:生成当前节点的邻居节点,并计算每个邻居节点的代价 f(n)=g(n)+h(n)。
  4. 更新列表:如果邻居节点未被访问过,或通过当前节点到达该邻居的路径比之前找到的更优,将其加入开放列表或更新其代价。
  5. 重复步骤 2-4,直到找到目标节点或开放列表为空。
  6. 输出结果:如果找到目标节点,则输出路径;如果开放列表为空且未找到目标,则表示无解。
代码实现(Python 示例)

以下是 A* 算法的简单实现示例:

import heapq

def a_star_search(graph, start, goal, h):
    open_list = []
    heapq.heappush(open_list, (0, start))  # 优先队列,存储 (f, node)
    came_from = {}  # 记录节点的前驱节点,用于回溯路径
    g_score = {start: 0}  # 从起点到当前节点的代价
    
    while open_list:
        _, current = heapq.heappop(open_list)  # 选择 f 最小的节点
        
        if current == goal:
            return reconstruct_path(came_from, current)
        
        for neighbor, cost in graph[current].items():
            tentative_g_score = g_score[current] + cost
            if neighbor not in g_score or tentative_g_score < g_score[neighbor]:
                came_from[neighbor] = current
                g_score[neighbor] = tentative_g_score
                f_score = tentative_g_score + h(neighbor)
                heapq.heappush(open_list, (f_score, neighbor))
    
    return None  # 未找到路径

def reconstruct_path(came_from, current):
    path = [current]
    while current in came_from:
        current = came_from[current]
        path.append(current)
    return path[::-1]  # 返回反转后的路径

# 示例图(使用邻接表表示)
graph = {
    'A': {'B': 1, 'C': 4},
    'B': {'A': 1, 'C': 2, 'D': 5},
    'C': {'A': 4, 'B': 2, 'D': 1},
    'D': {'B': 5, 'C': 1}
}

# 启发函数(例如:使用曼哈顿距离)
def heuristic(node):
    heuristics = {
        'A': 7,
        'B': 6,
        'C': 2,
        'D': 0
    }
    return heuristics.get(node, 0)

# 执行 A* 搜索
start, goal = 'A', 'D'
path = a_star_search(graph, start, goal, heuristic)
print("Path found:", path)

A* 算法的特点

  • 优点:当启发函数是可接受或一致时,A* 算法能保证找到最优解。
  • 缺点:由于需要维护开放列表,且需要计算所有节点的估计代价,A* 算法的空间和时间复杂度较高,尤其在搜索空间非常大的情况下。

应用场景

  1. 路径规划:例如机器人导航、游戏中的路径寻找等。
  2. 问题求解:例如八数码问题、滑块拼图等。
  3. 人工智能:例如在博弈树中寻找最佳策略。
  4. 优化问题:例如求解组合优化问题,如旅行商问题。

总结

启发式搜索通过使用启发函数来指导搜索过程,减少了搜索空间,提高了搜索效率。A* 算法作为启发式搜索的代表,能够在保证最优性的前提下高效地找到解。虽然启发式搜索的效率依赖于启发函数的质量,但它在路径规划、优化问题等方面的应用非常广泛。

  • 13
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

战族狼魂

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值