读书笔记 《算法图解》第八章 贪婪算法
8.1教室调度问题
emmm很显而易见是 美术 + 数学 + 音乐
连着上三堂课不会吐吗
贪婪算法就是 每步都是最优解 最终达到全局最优解
8.2贪婪算法并不总对 —— 背包问题
假设你是个小偷你要偷东西,按贪婪算法来说:
此时的最优解应该是 电脑 + 吉他 = 3500 > 3000
不过呢 其实也差不多
所以在很多时候 完美是优秀的敌人 用个贪婪算法大差不差也不是不可以
8.3 集合覆盖问题
假设你办了个广播节目,要让全美50个州的听众都收听得到。为此,你力图在尽可能少的广播台播出。现有广播台名单如下。
每个广播台都覆盖特定的区域,不同广播台的覆盖区域可能重叠
如何找出覆盖全美50个州的最小广播台合集呢?
1)列出广播台的所有子集 2^n
2)选出覆盖州最多且数量最少的子集
运行时间(大O表示法)
找出所有子集的时间 O(n^2)
问题是,如果n的数量增大,时间会急速增长。
此时 贪婪算法 成了该问题的近似算法:
每一次都选出覆盖最多的州,就算后面有重合也没关系,重复步骤直到覆盖了所有州。
衡量近似算法优劣的标准
- 速度有多快
- 得到的近似解和最优解的相似程度
贪婪算法速度快,大概为O(n^2)
代码部分
# 创建一个列表,其中包含了要覆盖的州
states_needed = set(['mt', 'wa', 'or', 'id', 'nv', 'ut', 'ca', 'az'])
# 创建可供选择的广播台清单,用dic来表示它们
stations = {}
stations['kone'] = set(['id', 'nv', 'ut'])
stations['ktwo'] = set(['wa', 'id', 'mt'])
stations['kthree'] = set(['or', 'nv', 'ca'])
stations['kfour'] = set(['nv', 'ut'])
stations['kive'] = set(['ca', 'az'])
# 写一个集合来表示最后选择的广播台
final_stations = set()
# 最佳电台(当前没有) 和 覆盖州
while states_needed:
best_station = None
states_covered = set()
for station, states_for_station in stations.items():
covered = states_for_station & states_needed
if len(covered) > len(states_covered):
best_station = station
states_covered = covered
final_stations.add(best_station)
states_needed -= states_covered
print(final_stations)
广度优先搜索和狄杰斯特拉算法都是贪婪算法
其实狄杰斯特拉算法的本质就是广度优先 在相邻的节点上选择而不是一条路线一条路线的选择 这就造成了可能会忽视含有负数加权的最优解。
8.4 NP完全问题
NP 完全问题的简单定义是,以难解著称的问题,如旅行商问题和合集覆盖问题。很多非常聪明的人都认为,根本不可能编写出可快速解决这些问题的算法。
NP问题的特点:
- 元素较少时算得贼快,较多时算的贼慢
- 一般需要整排列组合的问题
- 不能将问题分解成小问题,必须全局考虑
- 涉及序列(旅行商问题)且难以解决
- 涉及集合(电台问题)且难以解决
见到NP问题就要去寻找近似算法!