1、近似算法
近似算法 (approximation algorithm) 。 在获得精确解需要的时间太长时, 可使用近似算法。 判断近似算法优劣的标准如下:
- 速度有多快;
- 得到的近似解与最优解的接近程度。
集合覆盖问题算法举例
states_need=set(["mt", "wa", "or", "id", "nv", "ut","ca", "az"])#传入一个数组, 它被转换为集合
#可供选择的广播台清单
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["kfive"] = set(["ca", "az"])
#最终选择的广播台集合
final_stations=set()
while states_need:
best_station=None
states_covered=set()
for station,states_for_station in stations.items():
covered=states_need & states_for_station#求交集
if len(covered)>len(states_covered):
best_station=station
states_covered=covered
states_need-=states_covered
final_stations.add(best_station)
贪婪算法和精确算法的运行时间比较:
2、NP完全问题
NP完全问题的简单定义是, 以难解著称的问题, 如旅行商问题和集合覆盖问题。 很多非常聪明的人都认为, 根本不可能编写出可快速解决这些问题的算法。
判断NP完全问题:
- 元素较少时算法的运行速度非常快, 但随着元素数量的增加, 速度会变得非常慢。
- 涉及“所有组合”的问题通常是NP完全问题。
- 不能将问题分成小问题, 必须考虑各种可能的情况。 这可能是NP完全问题。
- 如果问题涉及序列(如旅行商问题中的城市序列) 且难以解决, 它可能就是NP完全问题。
- 如果问题涉及集合(如广播台集合) 且难以解决, 它可能就是NP完全问题。
- 如果问题可转换为集合覆盖问题或旅行商问题, 那它肯定是NP完全问题。
3、小结
- 贪婪算法寻找局部最优解, 企图以这种方式获得全局最优解。
- 对于NP完全问题, 还没有找到快速解决方案。
- 面临NP完全问题时, 最佳的做法是使用近似算法。
- 贪婪算法易于实现、 运行速度快, 是不错的近似算法。
4、练习
- 你在一家家具公司工作, 需要将家具发往全国各地, 为此你需要将箱子装上卡车。 每个箱子的尺寸各不相同, 你需要尽可能利用每辆卡车的空间, 为此你将如何选择要装上卡车的箱子呢? 请设计一种贪婪算法。 使用这种算法能得到最优解吗?
一种贪婪策略是, 选择可装入卡车剩余空间内的最大箱子, 并重复这个过程, 直到不能再装入箱子为止。 使用这种算法不能得到最优解。
- 你要去欧洲旅行, 总行程为7天。 对于每个旅游胜地, 你都给它分配一个价值——表 示你有多想去那里看看, 并估算出需要多长时间。你如何将这次旅行的价值最大化? 请设计一种贪婪算法。 使用这种算法能得到最优解吗?
不断地挑选可在余下的时间内完成的价值最大的活动, 直到余下的时间不够完成任何活动为止。 使用这种算法不能得到最优解。
- 下面各种算法是否是贪婪算法。
快速排序。
不是
广度优先搜索。
是
狄克斯特拉算法。
是
- 有个邮递员负责给20个家庭送信, 需要找出经过这20个家庭的最短路径。 请问这是一个NP完全问题吗?
是
- 在一堆人中找出最大的朋友圈(即其中任何两个人都相识) 是NP完全问题吗?
是
- 你要制作美国地图, 需要用不同的颜色标出相邻的州。 为此, 你需要确定最少需要使用多少种颜色, 才能确保任何两个相邻州的颜色都不同。 请问这是NP完全问题吗?
是