zoukankan      html  css  js  c++  java
  • 贪心算法解决集合覆盖问题

    贪心算法:指在对问题求解时,在每一步都选择最好的选择,从而希望得到最好的结果。
    解决集合覆盖问题
    比如有5个广播台,每个广播台覆盖的区域不一样,怎么选择最少的广播台,让所有区域都覆盖上
    如 k1广播台覆盖的区域有:北京、上海、天津
    k2广播台覆盖的区域有:北京、山东、深圳
    k3广播台覆盖的区域有:成都、上海、杭州
    k4广播台覆盖的区域有:上海、天津
    k5广播台覆盖的区域有:杭州、武汉

    步骤:
    1. 遍历所有广播台,找到了个覆盖了最多未覆盖的地区的电台
    2. 将这个电台加入到集合中,想办法将该电台覆盖的地区下次比较时去掉
    3. 重复第1步,直到覆盖了全部区域

    图解
    所有区域:{北京、上海、天津、山东、深圳、成都、杭州、武汉};
    选择的电台:{}

    第一步:遍历所有广播台,找到了个覆盖了最多未覆盖的地区的电台
    k1(北京、上海、天津),k2(北京、山东、深圳),k3(成都、上海、杭州)在所有区域({北京、上海、天津、山东、深圳、成都、杭州、武汉})中覆盖的个数为3
    k4(上海、天津),k5(杭州、武汉)在在所有区域({北京、上海、天津、山东、深圳、成都、杭州、武汉})中覆盖的个数为2
    选择最大覆盖数k1加入到选择的电台{k1},
    第二步:将k1(北京、上海、天津)从所覆盖的区域从所有区域中移除,所有区域更新为:{山东、深圳、成都、杭州、武汉};

    第三步:重复第一步,遍历所有广播
    k1(北京、上海、天津)在所有区域({山东、深圳、成都、杭州、武汉})中覆盖的个数为0
    k2(北京、山东、深圳)在所有区域({山东、深圳、成都、杭州、武汉})中覆盖的个数为2
    k3(成都、上海、杭州)在所有区域({山东、深圳、成都、杭州、武汉})中覆盖的个数为2
    k4(上海、天津)在所有区域({山东、深圳、成都、杭州、武汉})中覆盖的个数为0
    k5(杭州、武汉)在所有区域({山东、深圳、成都、杭州、武汉})中覆盖的个数为2
    选择最大覆盖数k2加入到选择的电台{k1,k2}
    将k2(北京、山东、深圳)从所覆盖的区域从所有区域中移除,所有区域更新为:{成都、杭州、武汉};
    k1(北京、上海、天津)在所有区域({成都、杭州、武汉})中覆盖的个数为0
    k2(北京、山东、深圳)在所有区域({成都、杭州、武汉})中覆盖的个数为0
    k3(成都、上海、杭州)在所有区域({成都、杭州、武汉})中覆盖的个数为2
    k4(上海、天津)在所有区域({成都、杭州、武汉})中覆盖的个数为0
    k5(杭州、武汉)在所有区域({成都、杭州、武汉})中覆盖的个数为2

    选择最大覆盖数k3加入到选择的电台{k1,k2,k3}
    将k3(成都、上海、杭州)从所覆盖的区域从所有区域中移除,所有区域更新为:{武汉};
    k1(北京、上海、天津)在所有区域({成都、杭州、武汉})中覆盖的个数为0
    k2(北京、山东、深圳)在所有区域({成都、杭州、武汉})中覆盖的个数为0
    k3(成都、上海、杭州)在所有区域({成都、杭州、武汉})中覆盖的个数为0
    k4(上海、天津)在所有区域({成都、杭州、武汉})中覆盖的个数为0
    k5(杭州、武汉)在所有区域({成都、杭州、武汉})中覆盖的个数为1

    选择最大覆盖数k5加入到选择的电台{k1,k2,k3,k5}
    完成

    代码实现:

    package azhong.greedy_algo;
    
    import java.util.*;
    
    /**
     * 贪心算法
     * 在对问题求解时,在每一步都选择最好的选择,从而希望得到最好的结果。
     */
    public class GreedyAlgoDemo {
        public static void main(String[] args) {
            //每个电台覆盖的区域
            Map<String,HashSet<String>> allStations = initRadioStation();
            //需要覆盖的所有区域
            HashSet<String> allAreas = getAllAreas(allStations);
            //存放选择的电台
            List<String> selectedStations = new ArrayList<>();
            while (allAreas.size()>0) {
                //遍历所有广播台,找到了个覆盖了最多未覆盖的地区的电台
                int maxIndex=0;
                String maxK=null;
                HashSet<String> areaInMaxK=null;
                for (Map.Entry<String, HashSet<String>> entry : allStations.entrySet()) {
                    final String k = entry.getKey();
                    HashSet<String> values = entry.getValue();
                    //当前电台在所有区域覆盖的个数
                    int c = testIntersectionOfSet(values, allAreas);
                    System.out.println(k + " 在所有区域覆盖的个数: " + c);
                    if(c>maxIndex){
                        maxIndex=c;
                        maxK=k;
                        areaInMaxK=values;
                    }
                }
                if(maxK!=null){
                    //选择最大覆盖数k1加入到选择的电台{k1},
                    selectedStations.add(maxK);
                    //将k1(北京、上海、天津)从所覆盖的区域从所有区域中移除,所有区域更新为:{山东、深圳、成都、杭州、武汉};
                    allAreas.removeAll(areaInMaxK);
                    //重置,进入下一次循环
                    maxIndex=0;
                    maxK=null;
                    areaInMaxK=null;
                    System.out.println("****************************");
                }
            }
            System.out.println(selectedStations);
        }
    
        /**
         * 测试:求两个集合的交集
         * A{北京、上海、天津}
         * B{北京、上海、天津、山东、深圳、成都、杭州、武汉}
         * A.retainAll(B); 得到A{北京、上海、天津} 个数为3
         */
        private static int testIntersectionOfSet(HashSet A,HashSet B){
            //将存在于集合A中但不存在于集合B中的元素移除。
            A.retainAll(B);
            return A.size();
        }
    
        /**
         * 初始化电台
         * k1广播台覆盖的区域有:北京、上海、天津
         * k2广播台覆盖的区域有:北京、山东、深圳
         * k3广播台覆盖的区域有:成都、上海、杭州
         * k4广播台覆盖的区域有:上海、天津
         * k5广播台覆盖的区域有:杭州、武汉
         * @return Map<String,HashSet<String>>类型电台集合
         */
        private static Map<String,HashSet<String>> initRadioStation(){
            Map<String,HashSet<String>> allStations = new HashMap<String,HashSet<String>>();
            HashSet<String> k1 = new HashSet<>();
            k1.add("北京");
            k1.add("上海");
            k1.add("天津");
            HashSet<String> k2 = new HashSet<>();
            k2.add("北京");
            k2.add("山东");
            k2.add("深圳");
            HashSet<String> k3 = new HashSet<>();
            k3.add("成都");
            k3.add("上海");
            k3.add("杭州");
            HashSet<String> k4 = new HashSet<>();
            k4.add("上海");
            k4.add("天津");
            HashSet<String> k5 = new HashSet<>();
            k5.add("杭州");
            k5.add("武汉");
            allStations.put("k1",k1);
            allStations.put("k2",k2);
            allStations.put("k3",k3);
            allStations.put("k4",k4);
            allStations.put("k5",k5);
            return allStations;
        }
    
        private static HashSet<String> getAllAreas(Map<String,HashSet<String>> allStations){
            HashSet<String> allAreas = new HashSet<>();
            Collection<HashSet<String>> stations = allStations.values();
            for(HashSet<String> station:stations){
                Iterator<String> areas = station.iterator();
                //操泥玛,写成了if
                while (areas.hasNext()){
                    allAreas.add(areas.next());
                }
            }
            return allAreas;
        }
    }

     运行结果为:

    k1 在所有区域覆盖的个数: 3
    k2 在所有区域覆盖的个数: 3
    k3 在所有区域覆盖的个数: 3
    k4 在所有区域覆盖的个数: 2
    k5 在所有区域覆盖的个数: 2
    ****************************
    k1 在所有区域覆盖的个数: 0
    k2 在所有区域覆盖的个数: 2
    k3 在所有区域覆盖的个数: 2
    k4 在所有区域覆盖的个数: 0
    k5 在所有区域覆盖的个数: 2
    ****************************
    k1 在所有区域覆盖的个数: 0
    k2 在所有区域覆盖的个数: 0
    k3 在所有区域覆盖的个数: 2
    k4 在所有区域覆盖的个数: 0
    k5 在所有区域覆盖的个数: 2
    ****************************
    k1 在所有区域覆盖的个数: 0
    k2 在所有区域覆盖的个数: 0
    k3 在所有区域覆盖的个数: 0
    k4 在所有区域覆盖的个数: 0
    k5 在所有区域覆盖的个数: 1
    ****************************
    [k1, k2, k3, k5]

  • 相关阅读:
    【整理】Linux 下 自己使用的 debug宏 printf
    STM32学习笔记:创建标准库工程模板
    【闲谈】第一份实习(下)
    Ceres-Solver库入门
    ceres-solver库使用示例
    ceres-solver库编译说明
    October 23, 2013
    Pollution over East China : Image of the Day
    谈谈PCI的GXL
    InfoQ访谈:Webkit和HTML5的现状和趋势
  • 原文地址:https://www.cnblogs.com/huangzhen22/p/14551864.html
Copyright © 2011-2022 走看看