目录
案例一:找零钱
案例二:活动安排
案例三:单源最短路径
贪心算法(Greedy Algorithm)是一种基于贪心策略的算法设计方法,它在每一步选择中都采取当前状态下最优的选择,以期望达到全局最优解。贪心算法通常适用于那些具有最优子结构性质的问题,即问题的最优解可以通过子问题的最优解来构造。
贪心算法的基本思想可以简单概括为:
选择策略:在每一步,从所有可选的选择中选择当前看起来最优的那个。
局部最优:通过选择局部最优解来构建全局最优解。
无后效性:每一步的选择只依赖于当前状态,不受之后的影响。
尽管贪心算法在许多情况下能够得到高效的解决方案,但它并不适用于所有问题。因为它没有考虑全局的状态,有时可能会导致得到次优解或者根本无法得到解。
问题:假设你是一个收银员,你需要找给顾客一定数量的零钱。你手上有一些面额不同的硬币(比如1元、5元、10元、20元、50元)。目标是找给顾客最少数量的硬币。
方法:
优先使用大面额的硬币。
如果顾客需要的金额超过当前最大面额的硬币,就使用一个最大面额的硬币,然后继续往下找零。
重复上述步骤,直到找完所有需要的零钱。
def give_change(amount, coins):
coins.sort(reverse=True) # 按面额从大到小排序
change = [] # 用来存放找零的硬币列表
for coin in coins:
while amount >= coin:
change.append(coin)
amount -= coin
return change
# 测试
amount = 30
coins = [1, 5, 10, 20, 50]
change = give_change(amount, coins)
print("找零的硬币列表:", change)
问题:假设你是一个活动策划师,现在你手上有一系列活动,每个活动都有一个开始时间和结束时间。你希望安排尽可能多的活动,但是由于时间的限制,你不能同时安排两个活动。你的目标是找出安排的最大数量的活动。
方法:
首先,将所有活动按照结束时间从早到晚排序。
选择第一个结束时间最早的活动,并将其安排上日程。
依次考虑后续活动,如果活动的开始时间晚于或等于上一个活动的结束时间,则可以安排该活动。
重复上述步骤,直到所有活动都考虑完毕。
def activity_selection(start_times, end_times):
# 将开始时间和结束时间打包成一个元组列表
activities = list(zip(start_times, end_times))
# 按结束时间从早到晚排序
activities.sort(key=lambda x: x[1])
selected_activities = []
end_time = 0
for activity in activities:
start, end = activity
if start >= end_time:
selected_activities.append(activity)
end_time = end
return selected_activities
# 测试
start_times = [1, 3, 0, 5, 3, 5, 6, 8]
end_times = [4, 5, 6, 7, 8, 9, 10, 11]
selected = activity_selection(start_times, end_times)
# 输出选中的活动
print("选中的活动:", selected)
问题:给定一个带权重的有向图和一个起始节点,我们想要找到从起始节点到图中所有其他节点的最短路径。
方法:Dijkstra算法,其基本思想贪心算法。
初始化:为每个节点设置一个距离值,初始时将起始节点的距离设为0,其他节点的距离设为无穷大。将所有节点放入一个优先队列(最小堆)中,按照距离值进行排序。
选择最近节点:从优先队列中取出距离起始节点最近的节点。
更新相邻节点的距离:对于被选中的节点,遍历其所有相邻节点,更新它们的距离值。如果通过当前节点到达相邻节点的路径比之前计算的路径更短,就更新相邻节点的距离值。
重复步骤2和3:重复选择最近节点和更新相邻节点的距离,直到所有节点都被处理过或者优先队列为空。
最终结果:当所有节点都被处理完毕后,得到了从起始节点到所有其他节点的最短路径。
import heapq
def dijkstra(graph, start):
distances = {node: float('infinity') for node in graph}
distances[start] = 0
priority_queue = [(0, start)]
while priority_queue:
current_distance, current_node = heapq.heappop(priority_queue)
if current_distance > distances[current_node]:
continue
for neighbor, weight in graph[current_node].items():
distance = current_distance + weight
if distance < distances[neighbor]:
distances[neighbor] = distance
heapq.heappush(priority_queue, (distance, neighbor))
return distances
# 示例图的邻接表表示
graph = {
'A': {'B': 10, 'C': 5},
'B': {'D': 5},
'C': {'B': 1, 'D': 2},
'D': {'A': 3}
}
# 使用Dijkstra算法找到从A到所有其他节点的最短路径
shortest_paths = dijkstra(graph, 'A')
# 输出最短路径
for node, distance in shortest_paths.items():
print(f'Shortest path from A to {node} is {distance}')