贪心算法之集合覆盖问题详解

Posted mx_info

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了贪心算法之集合覆盖问题详解相关的知识,希望对你有一定的参考价值。

贪心算法之集合覆盖问题详解

说明

  1. 贪心算法是指在对某一问题求解时,每一步都寻找最优解的一种思路
  2. 集合覆盖问题指有多个电台,每个电台都可以覆盖一定的区域,求可以覆盖所有地区的最小电台数量
  3. 使用贪心算法求得的解不一定是最优解,但是接近最优解
  4. 电台覆盖问题思路???
  5. 先用集合记录要覆盖的所有区域,然后遍历每一个电台,将每一个电台能覆盖到的区域和所有的电台做交集处理,然后得到能覆盖最大区域的电台,将这个电台保存
  6. 下一次,将已经覆盖过的区域从集合中删除得到未覆盖区域的新的集合,然后再遍历所有的电台,寻找能覆盖区域最多的电台
  7. 不断重复前述步骤,直到所有的区域都被覆盖
  8. 此问题在寻找电台时,优先使用可以覆盖区域最多的电台,使用了贪心算法的思想
  9. 源码见下

源码及分析

package algorithm.algorithm.greedy;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;

/**
 * @author AIMX_INFO
 * @version 1.0
 */
public class GreedyAlgorithm {
    public static void main(String[] args) {
        //创建键值对保存所有电台及其覆盖的区域
        HashMap<String, HashSet<String>> broadcasts = new HashMap<>();
        //创建每一个电台
        HashSet<String> hashSet1 = new HashSet<>();
        hashSet1.add("北京");
        hashSet1.add("上海");
        hashSet1.add("天津");
        HashSet<String> hashSet2 = new HashSet<>();
        hashSet2.add("广州");
        hashSet2.add("北京");
        hashSet2.add("深圳");
        HashSet<String> hashSet3 = new HashSet<>();
        hashSet3.add("成都");
        hashSet3.add("上海");
        hashSet3.add("杭州");
        HashSet<String> hashSet4 = new HashSet<>();
        hashSet4.add("上海");
        hashSet4.add("天津");
        HashSet<String> hashSet5 = new HashSet<>();
        hashSet5.add("杭州");
        hashSet5.add("大连");
        //添加所有电台
        broadcasts.put("K1",hashSet1);
        broadcasts.put("K2",hashSet2);
        broadcasts.put("K3",hashSet3);
        broadcasts.put("K4",hashSet4);
        broadcasts.put("K5",hashSet5);

        //电台要覆盖的所有地区
        HashSet<String> allAreas = new HashSet<>();
        for (Map.Entry<String, HashSet<String>> setEntry : broadcasts.entrySet()) {
            for (String area : setEntry.getValue()) {
                allAreas.add(area);
            }
        }
        //创建集合保存选择的电台
        ArrayList<String> selects = new ArrayList<>();
        //创建临时集合保存当前电台覆盖地区和所有未覆盖地区的交集
        HashSet<String> tmpSet = new HashSet<>();
        //定义maxKey保存包含最多未覆盖地区的电台
        String maxKey = null;
        //如果集合不为空,说明还要未覆盖的地区
        while (!allAreas.isEmpty()){
            maxKey = null;
            //取出每一个电台名字
            for (String key : broadcasts.keySet()) {
                tmpSet.clear();
                //拿到当前电台能覆盖的所有地区
                HashSet<String> area = broadcasts.get(key);
                //将这些地区添加到集合中
                tmpSet.addAll(area);
                //取tmpSet和allAreas集合的交集,将交集存储到tmpSet
                tmpSet.retainAll(allAreas);
                //如果当前这个集合覆盖的区域比maxKey包含的区域多
                if (tmpSet.size() > 0 && (maxKey == null || tmpSet.size() > broadcasts.get(maxKey).size())){
                    maxKey = key;
                }
            }
            //每次遍历都将覆盖过的去掉
            if (maxKey != null){
                selects.add(maxKey);
                allAreas.removeAll(broadcasts.get(maxKey));
            }
        }
        System.out.println(selects);
    }
}

以上是关于贪心算法之集合覆盖问题详解的主要内容,如果未能解决你的问题,请参考以下文章

贪心算法----区间覆盖问题(POJ2376)

算法导论习题—摊还时间代价分析栈实现队列贪心算法近似比集合覆盖问题

算法贪心算法

贪心算法之区间

贪心算法之Prim

程序员必会十大算法之贪心算法