toBeTheLight.github.io 荒原

阅读:《算法图解》(4)贪婪算法

2018-01-23
toBeTheLight

贪婪算法————简单而可能非最优的问题解决策略。 是一种能够得到某种度量意义下的最优解的分级处理方法,它总是做出在当前看来是最优的选择,也就是说贪心策略并不是从整体上加以考虑,它所做出的选择只是在某种意义上的局部最优解算法。

第八章 贪婪算法

教室调度问题

一个使用贪婪算法的例子

如何在有限的时间内安排最多的课程?

  1. 选出最早结束的课;
  2. 选出在最早结束的课后开始并最早结束的课;
  3. 循环;
  4. 搞定。

体现了两点:

  1. 简单;
  2. 局部最优解。

集合覆盖问题

一个使用贪婪算法的例子

有多个含有不同元素的集合,求全覆盖目标区域的最小集合组合。

步骤:

循环选出当前覆盖未范围最大的集合,并在此过程中从目标范围中移除已覆盖范围。

python代码

# 目标覆盖范围
states_needed = 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_needed:
    # 当前最优解
    best_station = None
    # 当前循环内集合最优覆盖范围
    states_covered = set()
    # 遍历所有集合
    for station, states_for_station in stations.items():
        # 当前遍历集合与待覆盖范围的交集
        covered = states_needed & states_for_station
        # 如果当前交集大于最优覆盖范围,则
        if len(covered) > len(states_covered):
            # 替换最优集合为当前遍历集合
            best_station = station
            # 更新当前循环内集合最优覆盖范围
            states_covered = covered
    # 将当次最优集合添加至最终结果
    final_stations.add(best_station)
    # 从目标覆盖范围中移除已覆盖范围
    states_needed -= states_covered
# 打印结果
print(final_stations)

NP完全问题

Non-deterministic Polynomial

简单的说NP完全问题是难以解决的问题,大多需要先列出所有的解,再找到最小的那个,复杂度会随元素数量急剧增加。类旅行商问题和集合覆盖问题可能就是NP完全问题。

小结

  • 贪婪算法寻找局部最优解,企图以这种方式获得全局最优解
  • 对于NP完全问题,还没有找到快速解决方案
  • 面临NP完全问题时,最佳的做法是使用近似算法
  • 贪婪算法易于实现,运行速度快,是不错的近似算法

相关文章

Content