NP完全问题与近似算法:贪婪策略|Python实现

1. 集合覆盖问题

假设我们创建了一个自己的电台,希望让整个市区的人都可以听到我们的节目。然而,这个城市有许多不同的广播公司,购买它们服务的电台可以让自己的节目覆盖某一块区域,并且这些区域常常是重叠的——这样,我们就面临 一个问题:如何找出可以覆盖全市的最少的广播台集合

我们使用一个简单的方法就可以得到完美的答案:

  1. 列出所有的广播台集合;
  2. 从这些集合中选择满足要求且最小的集合。

我们来考察一下第一步中需要多少个集合:

假设有n个电台,我们的集合中元素可能是任意1个、任意2个、任意3个、……、任意n个电台,这其实可以用组合数表示:
在这里插入图片描述
根据二项式定理:
在这里插入图片描述
我们的集合实际上有2n个,是一个指数。所以我们第一步得到的所有的集合组成的一个集合被称为**幂集**,它的子集个数为2的n次方个。这个算法的运行时间也可以表示为O(2n)。

我们来看看,假设计算机每秒可以计算出100个子集,让我们来看看时间:

广播台数n 所有的集合的数量 计算时间
5 32 0.32秒
10 1024 10.24秒
32 4 294 967 296 497天
100 1.2676506002282e+30 4×10^21年

当广播台数量较小时,计算机还可以处理这个问题,但当广播台数量n稍微增大一点——比如只是到了32,这个问题就变的无法计算了:计算时间变得很不现实。

2. NP完全问题

我们介绍了集合覆盖问题——我们要计算出所有的解,然后从中挑选出最小的。这很类似于我们前面介绍过的旅行商问题——我们同样需要列出所有的可能,然后挑选最短的,但不同的是我们记得旅行商问题的运行时间是O(n!)。

造成这种差异的原因是,在旅行商问题中,我们需要规划联通所有城市的最短路径,这涉及到的是序列,而非无序的集合(广播台问题涉及了集合),所以是排列问题而非组合问题。

集合覆盖问题和旅行商问题都是NP完全问题。我们可以认为NP完全问题就是难以解决的问题——无法编写出能完美解决这些问题的快速算法。

NP完全问题可能很难识别,比如求两个点之间的最短路径,我们可以用狄克斯特拉算法解决,而求解指定的几个点之间的最短路径就变成了旅行商问题——复杂的NP完全问题了。

我们给出一些用来判断的特点:

  1. 元素较少时运行速度非常快,但随着元素数量增加,运行速度变得非常慢的算法所要解决的问题可能是NP完全问题。
  2. 涉及“所有组合”的问题一般是NP完全问题。
  3. 必须考虑所有可能而无法将问题分解成小问题时可能是NP完全问题。
  4. 问题涉及序列(如旅行商问题)或集合(如集合覆盖问题)且难以解决时可能是NP完全问题。
  5. 集合覆盖问题和旅行商问题一定是NP完全问题(其实日常生活中,集合覆盖问题很常见 )。

3. 贪婪策略

对于NP完全问题,我们无法获得全局最优解。面对这类问题,我们可以使用贪婪策略:每步都选择局部最优解。采用这种策略之后得到的解可能是全局最优解,也可能非常接近全局最优解。但是,有时候完美往往会变成优秀的敌人——采用贪婪策略,我们虽然可能无法获得全局最优解,但是我们却可以用一种非常简单的方法获得一个优秀的答案。并且,在面对NP完全问题时,我们也只能使用贪婪策略。

下面让我们从两个例子中看看贪婪策略:每部都选择局部最优解,我们将得到一个优秀的最终解。在这两个例子中,我们将使用贪婪策略来快速、优秀的解决问题。

(1)教室调度问题:
  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值