zoukankan      html  css  js  c++  java
  • 2019.7.28

    说明:以下内容均参考:[美]Aditya Bhargava所著的《算法图解》

    贪婪算法:每步都寻找局部最优解,企图以这种方式获得全局最优解。

    贪婪算法的特点是速度快、简单且易于实现,可以作为解决NP完全问题的一种近似算法,但并非在任何情况下都行之有效。

    集合覆盖问题的一种近似算法便如下面的贪婪算法所示:

    (1)选出这样一个广播台,即它覆盖了最多的未覆盖州(即便这个广播台覆盖了一些已覆盖的州,也没有关系);

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

    在集合覆盖问题中,如果要寻找问题的精确解,则时间复杂度为(O(2^n)),而贪婪算法的时间复杂度为(O(n^2)),其中(n)为广播台数量。

    以上贪婪算法的代码如下:

    # 首先创建一个集合,其中包含要覆盖的州
    states_total = 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()
    
    # 算法的思路是每一次都在所有的广播台中寻找一个广播台,使得这个广播台能够在剩余的区域中覆盖的区域最大
    # 直至剩余的区域为空,循环停止
    # 前面的final_stations之所以使用set,是为了把重复找到的广播台自动过滤掉
    while states_total:
        best_station = None # 每一次的best_station和states_covered都要重新设置
        states_covered = set()
        for station, states in stations.items(): # 字典的items函数以列表返回可遍历的(key, values)元组数组
            covered = states_total & states # 集合的与运算
            if len(covered) > len(states_covered): # 找到能覆盖区域最多的广播台
                best_station = station
                states_covered = covered
        
        states_total -= states_covered # 每一次找到局部最优的广播台后,总的区域都要减掉这个广播台可覆盖的区域
        final_stations.add(best_station) # 并将这个局部最优广播台添加到final_stations中
                                         # 这里要注意,set不能用+的方式添加新元素,只能用add方法
    
    print(final_stations)
    

    关于NP完全问题,可以参考:https://www.jianshu.com/p/dcb0b52f4935

    NP完全问题的全称是:Non-deterministic Polynomial,即多项式复杂程度的非确定性问题。

    P类问题:所有可以在多项式时间内求解的判定问题构成P类问题。

    NP类问题:所有非确定性多项式时间内可解的判定问题构成NP类问题。

    旅行商问题:算法的时间复杂度强烈依赖于目标的数目,为(O(n!))

    旅行商问题和集合覆盖问题都属于NP完全问题,它们有一些共同之处:需要计算所有的解,并从中选取最优的那个。

    NP完全问题无处不在,但要判断问题是不是NP完全问题很难,易于解决的问题和NP完全问题的差别通常很小,但以下方法可以帮助识别是不是NP完全问题:

    (1)如果问题可转换为集合覆盖问题或旅行商问题,那它肯定是NP完全问题;

    (2)涉及“所有组合”的问题通常是NP完全问题;

    (3)不能将问题分成小问题,必须考虑各种可能的情况。这可能是NP完全问题;

    (4)如果问题涉及集合(如广播台集合)且难以解决,它可能就是NP完全问题;

    (5)如果问题涉及序列(如旅行商问题中的城市序列)且难以解决,它可能就是NP完全问题;

    (6)如果元素较少时算法的运行速度非常快,但随着元素数量的增加,速度会变得非常慢,它可能就是NP完全问题。

    对于NP完全问题,目前还没有找到可以快速解决的方案,最佳的做法是使用近似算法。

  • 相关阅读:
    【Android Developers Training】 73. 布局变化的动画
    【Android Developers Training】 72. 缩放一个视图
    【Android Developers Training】 71. 显示翻牌动画
    svn更改地址怎么办
    python学习手册
    failed to bind pixmap to texture
    Ubuntu 12.04安装Google Chrome
    svn update 时总是提示 Password for '默认密钥' GNOME keyring: 输入密码
    重设SVN 的GNOME keyring [(null)] 的密码
    Nginx + uWSGI + web.py 搭建示例
  • 原文地址:https://www.cnblogs.com/tbgatgb/p/11258679.html
Copyright © 2011-2022 走看看