数据结构(Java)贪心算法(分配广播站)

一、贪心算法介绍

1) 贪婪算法 ( 贪心算法 ) 是指在对问题进行求解时,在每一步选择中都采取最好或者最优 ( 即最有利 ) 的选择,从而希望能够导致结果是最好或者最优的算法
2) 贪婪算法所得到的结果 不一定是最优的结果 ( 有时候会是最优解 ) ,但是都是相对近似 ( 接近 ) 最优解的结果

 二、贪心算法最佳应用-集合覆盖

1) 假设存在如下表的需要付费的广播台,以及广播台信号可以覆盖的地区。 如何选择最少的广播台 ,让所有的地区都可以接收到信号

广播台

覆盖地区

K1

"北京", "上海", "天津"

K2

"广州", "北京", "深圳"

K3

"成都", "上海", "杭州"

K4

"上海", "天津"

K5

"杭州", "大连"

2) 思路分析 :
如何找出覆盖所有地区的广播台的集合呢,使用穷举法实现 , 列出每个可能的广播台的集合,这被称为幂集。假设总的有 n 个广播台,则广播台的组合总共有 2ⁿ -1 , 假设每秒可以计算 10 个子集, 如图 :

       

广播台数量n

子集总数2

需要的时间

5

32

3.2

10

1024

102.4

32

4294967296

13.6

100

1.26*100³º

4x10²³

        目前并没有算法可以快速计算得到准备的值, 使用贪婪算法,则可以得到非常接近的解,并且效率高。选择策略上,因为需要覆盖全部地区的最小集合:

1) 遍历所有的广播电台 , 找到一个覆盖了最多 未覆盖的地区 的电台 ( 此电台可能包含一些已覆盖的地区,但没有关系)
2) 将这个电台加入到一个集合中 ( 比如 ArrayList ), 想办法把该电台覆盖的地区在下次比较时去掉。
3) 重复第 1 步直到覆盖了全部的地区

三、代码演示

1.一些静态变量的初始化

class greedy {
    static List<String> coverageAreaOfFM100 = new ArrayList<>();
    static List<String> coverageAreaOfFM101 = new ArrayList<>();
    static List<String> coverageAreaOfFM102 = new ArrayList<>();
    static List<String> coverageAreaOfFM103 = new ArrayList<>();
    static List<String> coverageAreaOfFM104 = new ArrayList<>();
    static List<String> allArea = new ArrayList<>();//存储待覆盖城市

    static Map<String, List<String>> broadcastTable = new HashMap<>();
        //存放电台信息(名字+可覆盖区域)

    static int count=0;//记录第几次选择

... ...

 2.初始化城市、电台信息

  public static void init() {
        allArea.add("北京");
        allArea.add("上海");
        allArea.add("天津");
        allArea.add("广州");
        allArea.add("深圳");
        allArea.add("成都");
        allArea.add("杭州");
        allArea.add("大连");

        coverageAreaOfFM100.add("北京");
        coverageAreaOfFM100.add("上海");
        coverageAreaOfFM100.add("天津");

        coverageAreaOfFM101.add("广州");
        coverageAreaOfFM101.add("北京");
        coverageAreaOfFM101.add("深圳");

        coverageAreaOfFM102.add("成都");
        coverageAreaOfFM102.add("上海");
        coverageAreaOfFM102.add("杭州");

        coverageAreaOfFM103.add("上海");
        coverageAreaOfFM103.add("天津");

        coverageAreaOfFM104.add("杭州");
        coverageAreaOfFM104.add("大连");

        broadcastTable.put("FM100", coverageAreaOfFM100);
        broadcastTable.put("FM101", coverageAreaOfFM101);
        broadcastTable.put("FM102", coverageAreaOfFM102);
        broadcastTable.put("FM103", coverageAreaOfFM103);
        broadcastTable.put("FM104", coverageAreaOfFM104);
    }

3.打印电台信息

 public static void printBroadcastInformation() {
        System.out.println("城市列表:");
        System.out.println("-----------------------------------------");
        for (String e : allArea) System.out.print(" "+e);
        System.out.println("\n");
        System.out.println("广播台        覆盖地区");
        System.out.println("---------------------");
        for (Map.Entry<String, List<String>> entry : broadcastTable.entrySet()) {
            System.out.println(entry.getKey() + "       " + entry.getValue());
        }
    }

 4.计算每个广播站当前可以覆盖的地区数量

 //计算每个广播站当前可以覆盖的地区数量
    public static Map<String,Integer> countAreaCouldCover() {
        List<String> temp;
        Map<String,Integer> counts = new HashMap<>();
        for (Map.Entry<String, List<String>> entry : broadcastTable.entrySet()) {

    //用广播站可覆盖城市与当前剩余城市做交集,得到的就是当前该广播站可覆盖的区域
            temp = entry.getValue();
            temp.retainAll(allArea);
            counts.put(entry.getKey(),temp.size());
        }
        return counts;
    }

5.得到当前覆盖地区数量最大的广播台名字

//计算当前覆盖地区数量最大的广播台
    public static String maxKey( Map<String, Integer> countCovers) {
        int maxCovers=0;
        String maxKey="";
    //利用 4 中得到的 map 很容易求出最大可覆盖区域对应的电台名字
        for (Map.Entry<String, Integer> entry : countCovers.entrySet()){
               if(entry.getValue()>maxCovers) {
                   maxKey=entry.getKey();
                   maxCovers= entry.getValue();
               }
        }
        return maxKey;
    }

 6.主程序

 public static void broadcastCoverage() {
        List<String> selection=new ArrayList<>();
        // 1.初始化
        init();
        // 2.查看初始信息
        printBroadcastInformation();
        // 3.选择电台
        while (!allArea.isEmpty()){
            count++;
            //先把广播台名字加入结果中
            selection.add(maxKey(countAreaCouldCover()));
            System.out.println("-----------------------------------------");
            System.out.println("第"+count+"次选择: ");
            System.out.print("选择的电台:"+maxKey(countAreaCouldCover()));
            System.out.println(" , 选择的城市:"+broadcastTable.get(maxKey(countAreaCouldCover())));
            //再把对应的城市删除掉
            allArea.removeAll(broadcastTable.get(maxKey(countAreaCouldCover())));

            System.out.println("剩下的城市:");
            for (String e : allArea) System.out.print(e + " ");
            System.out.println();
        }
        System.out.print("结果为:");
        for(String e:selection) System.out.print(e+" ");
    }
城市列表:
-----------------------------------------
 北京 上海 天津 广州 深圳 成都 杭州 大连

广播台        覆盖地区
---------------------
FM104       [杭州, 大连]
FM102       [成都, 上海, 杭州]
FM103       [上海, 天津]
FM100       [北京, 上海, 天津]
FM101       [广州, 北京, 深圳]
-----------------------------------------
第1次选择: 
选择的电台:FM102 , 选择的城市:[成都, 上海, 杭州]
剩下的城市:
北京 天津 广州 深圳 大连 
-----------------------------------------
第2次选择: 
选择的电台:FM101 , 选择的城市:[广州, 北京, 深圳]
剩下的城市:
天津 大连 
-----------------------------------------
第3次选择: 
选择的电台:FM104 , 选择的城市:[大连]
剩下的城市:
天津 
-----------------------------------------
第4次选择: 
选择的电台:FM103 , 选择的城市:[天津]
剩下的城市:

结果为:FM102 FM101 FM104 FM103 
注: 贪婪算法所得到的结果不一定是 最优的结果 ( 有时候会是最优解 ) ,但是都是 相对近似 ( 接近 ) 最优解的结果
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值