应用场景:
有5个广播台K1,K2,K3,K4,K5每个广播台都有限定的播放地区,如图:
广播台 | 播放地区 |
---|---|
K1 | 北京、上海、天津 |
K2 | 广州、北京、深圳 |
K3 | 成都、上海、杭州 |
K4 | 上海、天津 |
K5 | 杭州、大连 |
问题:如何选取数量最少的广播台,覆盖北京、上海、天津、广州、深圳、成都、杭州、大连这8个城市?
贪心算法:
- HashSet存放未覆盖城市,北京、上海、天津、广州、深圳、成都、杭州、大连
- 遍历广播台找出含未覆盖城市最多的广播台
- 添加到答案中,并在未覆盖城市HashSet中移除该广播台所覆盖的城市
- 重复步骤2,直到未覆盖城市为0
贪心算法思想:每一次得到的解都是最优的
代码:
public class GreedyAlgorithm {
public static void main(String[] args) {
//广播台
Set<String> k1 = new HashSet<>();
k1.add("北京");
k1.add("上海");
k1.add("天津");
Set<String> k2 = new HashSet<>();
k2.add("广州");
k2.add("北京");
k2.add("深圳");
Set<String> k3 = new HashSet<>();
k3.add("成都");
k3.add("上海");
k3.add("杭州");
Set<String> k4 = new HashSet<>();
k4.add("上海");
k4.add("天津");
Set<String> k5 = new HashSet<>();
k5.add("杭州");
k5.add("大连");
//存放广播电台的信息,以及对应的覆盖地区
Map<String, Set<String>> broadcasts = new HashMap<>();
broadcasts.put("K1",k1);
broadcasts.put("K2",k2);
broadcasts.put("K3",k3);
broadcasts.put("K4",k4);
broadcasts.put("K5",k5);
//所有想覆盖的地区
Set<String> allAreas = new HashSet<>();
allAreas.add("北京");
allAreas.add("上海");
allAreas.add("天津");
allAreas.add("广州");
allAreas.add("深圳");
allAreas.add("成都");
allAreas.add("杭州");
allAreas.add("大连");
//存放所选的广播台
List<String> selects = new ArrayList<>();
//临时集合,来存放一个广播台含未覆盖的地区
Set<String> tempSet = new HashSet<>();
String maxKey = null;
int maxTempSetSize = 0;
while (allAreas.size() != 0){
maxKey = null;
maxTempSetSize = 0;
//遍历广播台,找出含未覆盖地区最多的广播台
for(String broadcast : broadcasts.keySet() ){
tempSet.clear();
Set<String> areas = broadcasts.get(broadcast);//获取该广播台所能覆盖到的范围
tempSet.addAll(areas);
tempSet.retainAll(allAreas);//用当前广播台能覆盖地区对所有未覆盖地区进行交集得出当前广播台含未覆盖的地区
if ( tempSet.size()>0 && (maxKey==null || tempSet.size() > maxTempSetSize) ){
maxKey = broadcast;
maxTempSetSize = tempSet.size();
}
}
if(maxKey!=null){
selects.add(maxKey);
allAreas.removeAll(broadcasts.get(maxKey));//移除 添加广播台 已覆盖的地区
}
}
System.out.println(selects);
}
}
>>>
[K1, K2, K3, K5]