一、启发式搜索相关思想
启发式搜索是一类基于估计值(启发式函数)来指导搜索的算法。其基本思想是利用启发信息来指导搜索过程,从而加速搜索并找到解决方案或更接近目标的解。启发信息通常由启发函数提供,该函数能够评估节点的重要性或接近目标的程度。在搜索过程中,启发式搜索算法会优先扩展那些更有可能包含解或更接近目标的节点,从而显著提高搜索效率。
二、启发式搜索技术
启发式搜索技术在计算机科学和人工智能领域有着广泛的应用,常见的启发式搜索算法包括A*算法、贪心算法等。以下是一些关键的技术要点:
- 状态表示:定义问题的状态表示方式,通常是一个数据结构,其中包含描述问题状态的所有必要信息。
- 启发式函数:实现一个启发式函数,用于评估当前状态到目标状态的距离或成本的估计。启发式函数的设计需要根据具体问题的特点,可以基于问题的领域知识或者简单的规则。
- 搜索策略:选择适合问题的搜索策略,常见的搜索策略包括A算法、IDA算法、Greedy Best-First Search等。
- 状态扩展:实现状态扩展操作,根据当前状态生成可能的后继状态。这通常涉及到问题定义中的状态转移操作。
- 搜索控制:实现搜索控制机制,用于管理搜索过程。这可能包括设置搜索深度限制、时间限制、启发式函数的阈值等,以控制搜索的规模和复杂度。
三、实例代码
贪心算法
- 原理:在对问题求解时,总是做出在当前看来是最好的选择,不考虑整体最优,只考虑局部最优。
- 实例:找零问题。假设有面值为5元、2元、1元、5角、2角、1角的硬币,要找给顾客9元8角。贪心算法的思路是每次都选择面值最大的硬币,先选1个5元硬币,再选2个2元硬币,然后选1个5角硬币,1个2角硬币和1个1角硬币,这样就用最少的硬币数量完成了找零。
def greedy_change(amount):
coins = [500, 200, 100, 50, 20, 10] # 硬币面值,单位为角
coin_count = [0] * len(coins)
for i, coin in enumerate(coins):
while amount >= coin:
amount -= coin
coin_count[i] += 1
return coin_count
amount = 980 # 9 元 8 角,单位为角
result = greedy_change(amount)
coin_names = ["5 元", "2 元", "1 元", "5 角", "2 角", "1 角"]
for i in range(len(result)):
if result[i] > 0:
print(f"{coin_names[i]}: {result[i]} 个")
A*算法
- 原理:综合考虑节点的路径代价和到目标节点的估计代价,通过评估函数(f(n)=g(n)+h(n))来选择下一个要扩展的节点,其中(g(n))是从起始节点到节点(n)的实际代价,(h(n))是从节点(n)到目标节点的估计代价。
- 实例:在地图导航中,要从A地到B地,A算法会根据当前位置到已走过位置的距离(g(n)),以及当前位置到B地的直线距离估计值(h(n))(启发函数)来选择下一个要走的节点。比如在一个城市道路网络中,计算从当前路口到目标路口的最短路径,A算法会综合考虑已经走过的路程和到目标路口的直线距离等因素,快速找到最优路径。
import heapq
# 定义节点类
class Node:
def __init__(self, x, y, g=float('inf'), h=float('inf'), parent=None):
self.x = x
self.y = y
self.g = g
self.h = h
self.f = g + h
self.parent = parent
def __lt__(self, other):
return self.f < other.f
# 曼哈顿距离作为启发函数
def heuristic(a, b):
return abs(a[0] - b[0]) + abs(a[1] - b[1])
# A* 算法实现
def a_star(grid, start, goal):
rows, cols = len(grid), len(grid[0])
open_list = []
closed_set = set()
start_node = Node(start[0], start[1], 0, heuristic(start, goal))
heapq.heappush(open_list, start_node)
while open_list:
current = heapq.heappop(open_list)
if (current.x, current.y) == goal:
path = []
while current:
path.append