贪心算法解决集合覆盖问题

问题描述:

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

广播台 覆盖地区
k1 “北京”,“上海,“天津””
k2 “广州”,“北京,“深圳””
k3 “成都”,“上海,“杭州””
k4 “上海,“天津””
k5 “杭州”,“大连”"
k6 “福州”,“重庆”"

贪心算法:

贪心算法(又称贪婪算法)是指,在对问题求解时,总是做出在当前看来是最好的选择。也就是说,不从整体最优上加以考虑,他所做出的是在某种意义上的局部最优解。

解决思路:

1.添加覆盖地区,并构建广播站

    HashSet hashSet1 = new HashSet<>();
    hashSet1.add("北京");
    hashSet1.add("上海");
    hashSet1.add("天津");

    HashSet hashSet2 = new HashSet<>();
    hashSet2.add("北京");
    hashSet2.add("广州");
    hashSet2.add("深圳");

    HashSet hashSet3 = new HashSet<>();
    hashSet3.add("成都");
    hashSet3.add("上海");
    hashSet3.add("杭州");

    HashSet hashSet4 = new HashSet<>();
    hashSet4.add("上海");
    hashSet4.add("天津");

    HashSet hashSet5 = new HashSet<>();
    hashSet5.add("杭州");
    hashSet5.add("大连");

    HashSet hashSet6 = new HashSet<>();
    hashSet6.add("福州");
    hashSet6.add("重庆");

    //构建广播台
    HashMap> broadcasts = new HashMap<>();
    broadcasts.put("k1", hashSet1);
    broadcasts.put("k2", hashSet2);
    broadcasts.put("k3", hashSet3);
    broadcasts.put("k4", hashSet4);
    broadcasts.put("k5", hashSet5);
    broadcasts.put("k6", hashSet6);

`

2.构建存放所有需要覆盖的地区的集合,每添加一个广播站就要从该集合中清除对应的地区;

 //存放所有需要覆盖的地区
        HashSet allAreas = new HashSet<>();
        for (Set areas : broadcasts.values()) {
            //只能addAll,add会出现[“北京”,“上海,“天津””][“广州”,“北京,“深圳””]按照集合的形式存在会有重复
            allAreas.addAll(areas);
        }

3.遍历广播站每次找出能覆盖待覆盖区域数最多的广播站,这一步就是贪心算法的体现,局部最优

完整java代码实现:

package com.yg.algorithm;/*
@author  Mu_Mu
@date    2020/3/19  10:15
*/

import java.util.*;

public class GreedyAlogorithm {
    public static void main(String[] args) {
        //添加覆盖地区
        HashSet hashSet1 = new HashSet<>();
        hashSet1.add("北京");
        hashSet1.add("上海");
        hashSet1.add("天津");

        HashSet hashSet2 = new HashSet<>();
        hashSet2.add("北京");
        hashSet2.add("广州");
        hashSet2.add("深圳");

        HashSet hashSet3 = new HashSet<>();
        hashSet3.add("成都");
        hashSet3.add("上海");
        hashSet3.add("杭州");

        HashSet hashSet4 = new HashSet<>();
        hashSet4.add("上海");
        hashSet4.add("天津");

        HashSet hashSet5 = new HashSet<>();
        hashSet5.add("杭州");
        hashSet5.add("大连");

        HashSet hashSet6 = new HashSet<>();
        hashSet6.add("福州");
        hashSet6.add("重庆");

        //构建广播台
        HashMap> broadcasts = new HashMap<>();
        broadcasts.put("k1", hashSet1);
        broadcasts.put("k2", hashSet2);
        broadcasts.put("k3", hashSet3);
        broadcasts.put("k4", hashSet4);
        broadcasts.put("k5", hashSet5);
        broadcasts.put("k6", hashSet6);

        //存放所有需要覆盖的地区
        HashSet allAreas = new HashSet<>();
        for (Set areas : broadcasts.values()) {
            //只能addAll,add会出现[“北京”,“上海,“天津””][“广州”,“北京,“深圳””]按照集合的形式存在会有重复
            allAreas.addAll(areas);
        }

        //存放需要选择的广播站列表
        ArrayList broadList = new ArrayList<>();
        //maxKey代表能覆盖待覆盖区域最大的广播站
        String maxKey = null;
        int maxNum = 0;//能覆盖待覆盖区域最大的数量
        //只要allAreas.size() >0说明还有地区需要被覆盖
        //存放能覆盖待覆盖的区域
        HashSet tempSet = new HashSet<>();
        while (allAreas.size() > 0) {
            maxKey = null;
            for (String key : broadcasts.keySet()) {
                tempSet.clear();
                tempSet.addAll(broadcasts.get(key));
                tempSet.retainAll(allAreas);
                if (tempSet.size() > 0 && (maxKey == null || tempSet.size() > maxNum)) {
                    maxKey = key;
                    maxNum = tempSet.size();
                }
            }
            if (maxKey != null) {
                broadList.add(maxKey);
                //从待覆盖区域的集合中移除这次新增覆盖区域
                allAreas.removeAll(broadcasts.get(maxKey));
            }
        }
        System.out.println("待添加的广播站有:");
        for (String str : broadList) {
            System.out.print(str+" ");
        }

    }
}


你可能感兴趣的:(算法)