首页 > 编程语言 >NP 完全问题和贪婪算法

NP 完全问题和贪婪算法

时间:2023-01-19 12:04:03浏览次数:45  
标签:states set stations 问题 集合 算法 贪婪 NP

什么是NP完全问题:
算法导论中这样描述NP完全问题:在多项式时间内可解的问题是易处理的问题,在超多项式时间内解决的问题是不易处理的问题。NP完全问题就是后者。通俗说就是:以难解著称的问题,比如旅行商问题和集合覆盖问题,人们普遍认为这些问题,不可能编写出可快速解决的算法。

旅行商问题:

一个旅行商要前往5个不同的城市,同时确保行程最短。如何计算最短的行程。5个城市有120种组合。这是一个阶乘问题,随着城市数目的增加,运行时间增长非常快。无法快速解出。

集合覆盖问题:

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

把一个广播包覆盖的州作为一个集合,有n个不同的集合,每个集合包含若干州,如果覆盖所有州的最小集合个数。这里的组合有2的n次方个。我们称为幂集。计算时间为O(2^n) 如果n是100,每秒可以计算10万个子集,花费的时间将是一个天文数字。

所以针对NP完全问题,我们无法给出快速求取精确解的算法。所以我们一般用近似算法来解决此类问题,获取一个近似解。

近似算法优劣的两个标准:

1.速度有多快

2.得到的近似解和最优解接近程度

贪婪算法:
贪婪算法(或贪心算法) 是近似算法的一种。贪心算法的核心思想是:每一步都选择局部最优解,最终得到的就是最优解。

旅行商问题:先随便找一个城市作为起点城市,然后每次都选剩余城市中距离当前城市最近的一个城市,直到选择完毕。

集合覆盖问题:

1.选出这样一个集合,它覆盖了最多的未覆盖的城市。

2.重复第一步,直到覆盖所有城市。

算法实现:
出于简化考虑,这里假设要覆盖的州没有那么多,广播台也没有那么多

stations = {}
stations["ktwo"] = set(["wa", "id", "mt"])
stations["kone"] = set(["id", "nv", "ut","wa","mt"])
stations["kthree"] = set(["or", "nv", "ca"])
stations["kfour"] = set(["nv", "ut"])
stations["kfive"] = set(["ca", "az"])


完整代码:

#最终要覆盖的所有州
states_needed = set(["mt", "wa", "or", "id", "nv", "ut", "ca", "az"])

#该散列表用来记录每个广播台和其覆盖的州
stations = {}
stations["ktwo"] = set(["wa", "id", "mt"])
stations["kone"] = set(["id", "nv", "ut","wa","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 in stations.items():
#计算两个集合的交集
covered = states_needed & states
if len(covered) > len(states_covered):
best_station = station
states_covered = covered

#排除已经选择的集合中覆盖的州
states_needed -= states_covered
final_stations.add(best_station)


print(final_stations)

小结:

贪心算法的特点是简单快速。核心思想是不断选择局部最优解,获得最终的解。结果是一个近似解。

如何识别NP完全问题:
断问题是不是NP完全问题很难,易于解决的问题和NP完全问题的差别通常很小。以下一些特征可以作为参考:

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

标签:states,set,stations,问题,集合,算法,贪婪,NP
From: https://www.cnblogs.com/oceaning/p/17061251.html

相关文章