当前位置:   article > 正文

贪心算法(集合覆盖问题)

集合覆盖问题

一、贪心算法概述

贪心算法的核心思想可以总结为:贪心算法总是做出在当前看来最好的选择。

也就是说贪心算法并不从整体最优考虑,它所做出的选择只是在某种意义上的局部最优选择。当然,希望贪心算法得到的最终结果也是整体最优的。

虽然贪心算法不能对所有问题都得到整体最优解,但对许多问题它能产生整体最优解,如单源最短路经问题,最小生成树问题等。虽然在一些情况下,即使贪心算法不能得到整体最优解,但其最终结果却是最优解的很好近似。

二、集合覆盖问题

2.1 问题描述

假设你办了个广播节目,要让国内的 8 个重要城市的听众都收听得到。为此,你需要决定在哪些广播台播出。在每个广播台播出都需要支付费用,因此你力图在尽可能少的广播台播出。现有广播台名单如下。

广播台 覆盖地区
K1 北京、上海、天津
K2 广州、北京、深圳
K3 成都、上海、杭州
K4 上海、天津
K5 杭州、大连

如何选择最少的广播台,让所有的城市都可以接收到信号?

2.2 集合覆盖问题的贪心算法

每个广播台都覆盖特定的区域,不通过的广播覆盖的区域可能是重叠的。如何找出覆盖 8 个城市的最小广播台集合呢?

首先我们最容易想到的办法就是穷举法:

  1. 列出每个可能的广播台的集合,可能的集合有 2ⁿ 个;
  2. 在这个集合中,选出能够覆盖 8 个城市的最小集合。

上面这个方法确实可以求得最终结果,但是问题在于 n 个广播台可能的集合有 2ⁿ 个,因此运行时间为 O(2ⁿ)。如果广播台不多,比如只有 5~10 个,这个方法倒还可行。但是一旦问题的规模变大,广播台的数量增多,需要的时间将激增。假设每秒可以计算出 10 个集合,那么所需的时间如下表所示:

广播台数量 需要的时间
5 3.2 秒
10 102.4 秒
32 13.6 年
100 4 x 10²¹ 年

显然,使用穷举所有集合的方法不是一个明智的选择。

针对这类集合覆盖问题,贪心算法是一个比较合适的算法,虽然贪心算法不一定能够得到最优解,但是它可以得到非常接近的解。

对于本题,贪心算法的基本思想如下:

  1. 优先选择出覆盖了最多未被覆盖的城市的广播台。即使这个广播台覆盖了一些已覆盖的城市也没关系;
  2. 重复第一步,直到选出的广播台覆盖了所有的城市。

可以看到,使用贪心算法解决集合覆盖问题的思路贯彻着 “选择当下看来最好的选择” 这样的思想。简单来说就是走好每一步路,最终得到的结果必定不会太差。

贪心算法不仅简单,而且运行速度也很快。对于本题,贪心算法的运行时间为 O(n²),其中 n 为广播台的数量。

2.3 代码实现

首先来说一下代码实现的思路:

  1. 创建一个集合 cities,存放所有的城市;
  2. 创建一个散列表 broadcast,广播站作为键,对应的城市作为值;
  3. 创建一个集合 selectedList,用于存放已选择的广播站;
  4. 遍历散列表,找到覆盖了最多未覆盖的城市的广播站,将其加入到已选择广播站集合 selectedList中;
  5. 将上一步选择的广播站所覆盖的城市从城市集合 cities 中移除,同时将广播站从散列表中移除;
  6. 重复执行 4、5 步,直至城市集合为空。

完整的代码实现如下 :

public static void main(String[] args) {
   
    HashMap<String, Set> broadcast = new HashMap<>();   // 用于存放广播和覆盖的城市
    HashMap<String, Set> selectedList = new HashMap<>(<
  • 1
  • 2
  • 3
声明:本文内容由网友自发贡献,转载请注明出处:【wpsshop】
推荐阅读
相关标签
  

闽ICP备14008679号