• 【算法】贪婪算法


    贪婪算法

    • 每步都采取最优的做法,即每步都选择局部最优解,最终得到的就是全局最优解。
    • 在有些情况下,贪婪策略显然不能获得最优解,但非常接近。完美是优秀的敌人,有时候,只需找到一个能够大致解决问题的算法,此时贪婪算法正好可派上用场,因为它们实现起来很容易,得到的结果又与正确结果相当接近。

    近似算法(approximation algorithm)

    在获得精确解需要的时间太长时,可使用近似算法。

    判断近似算法优劣的标准:

    • 速度有多快;
    • 得到的近似解与最优解的接近程度。

    示例

    有一个广播节目,要让全美50个州的听众都收听得到。为此,需要决定在哪些广播台播出。在每个广播台播出都需要支付费用,因此力图在尽可能少的广播台播出

    贪婪算法

    (1) 列出每个可能的广播台集合,这被称为幂集(power set)。可能的子集有2ⁿ个。

    (2) 在这些集合中,选出覆盖全美50个州的最小集合。

    近似算法

    (1) 选出这样一个广播台,即它覆盖了最多的未覆盖州。即便这个广播台覆盖了一些已覆盖

    的州,也没有关系。

    (2) 重复第一步,直到覆盖了所有的州。

    运行时间为O(n²),其中n为广播台数量

    代码

    #创建一个包含要覆盖州的集合
    states_needed = set(["mt", "wa", "or", "id", "nv", "ut","ca", "az"])
    
    #创建一个包含所有电台及其覆盖州的散列表
    stations={'kone': {'id', 'ut', 'nv'}, 'ktwo': {'wa', 'mt', 'id'}, 'kthree': {'or', 'ca','nv'}, 'kfour': {'ut', 'nv'}, 'kfive': {'az', 'ca'}}
    
    #创建一个集合存储最终选择的广播台
    final_stations=set()
    
    
    while states_needed:
        best_station = None #存储覆盖了最多的未覆盖州的广播台
        states_covered = set()  #包含该广播台覆盖的所有未覆盖的州。
        for station, states in stations.items():    #for循环迭代每个广播台,并确定它是否是最佳的广播台
            covered = states_needed & states   #包含同时出现在states_needed和states_for_station中的州
            if len(covered) > len(states_covered):  #如果该电台覆盖的州是否比best_station多
                best_station = station   #将best_station设置为当前广播台
                states_covered = covered
                
        states_needed -= states_covered   #由于该广播台覆盖了一些州,因此不用再覆盖这些州。
        final_stations.add(best_station)
    
    print(final_stations)
    

      

    NP完全问题

    定义

    以难解著称的问题。如旅行商问题和集合覆盖问题。

    需要计算所有的解,并从中选出最小/最短的那个

    NP完全问题,使用近似算法即可,无需求最优解

    如何识别 NP 完全问题

    • 元素较少时算法的运行速度非常快,但随着元素数量的增加,速度会变得非常慢。
    • 涉及“所有组合”的问题通常是NP完全问题。
    • 不能将问题分成小问题,必须考虑各种可能的情况。这可能是NP完全问题。
    • 如果问题涉及序列(如旅行商问题中的城市序列)且难以解决,它可能就是NP完全题。
    • 如果问题涉及集合(如广播台集合)且难以解决,它可能就是NP完全问题。
    • 如果问题可转换为集合覆盖问题或旅行商问题,那它肯定是NP完全问题。

    小结

    • 贪婪算法寻找局部最优解企图以这种方式获得全局最优解
    • 对于NP完全问题,还没有找到快速解决方案。
    • 面临NP完全问题时,最佳的做法是使用近似算法。
    • 贪婪算法易于实现、运行速度快,是不错的近似算法。
  • 相关阅读:
    C++ 如何重复利用一个内存地址块
    C与C++在const用法上的区别
    C++ 与设计模式学习(其一)
    C/C++ 关于生成静态库(lib)/动态库(dll)文件如何使用(基于windows基础篇)
    c/c++----网站及其后门(CGI应用程序)
    C/C++深度copy和浅copy
    C/C++ 一段代码区分数组指针|指针数组|函数指针|函数指针数组
    C/C++ 如何劫持别人家的命令||函数||程序(只能对于window而言)
    C++继承与派生(原理归纳)
    Linux下如何查看自己的服务器有没有无线网卡
  • 原文地址:https://www.cnblogs.com/lilip/p/9553347.html
Copyright © 2020-2023  润新知