贪心算法
集合覆盖问题:选择最少的广播台,让所有的地区都可以接受到信号
贪心算法是指在对问题进行求解时,在每一步选择中都采取最好或者最优的选择,从而希望能够导致结果是最好或最优的算法
贪心算法得到的结果不一定是最优的,但都是相对金丝猴最优解的结果
集合覆盖
如何找出覆盖所有地区的广播台的集合?使用穷举法实现,列出每个可能的广播台的集合,这时称为幂集。假设有n个广播台,则广播台的组合共有 2^n-1个,假设每秒可以计算10个子集
广播台数量n | 子集总数2^n | 需要的时间 |
---|---|---|
5 | 32 | 3.2s |
10 | 1024 | 102.4s |
32 | 4294967296 | 13.6years |
100 | 1.26*100^32 | 4*10^23years |
- 遍历所有的广播电台,找到一个覆盖了最多未覆盖的地区的电台(此电台可能包含一些已覆盖的地区,但没有关系)
- 将这个电台加入到一个集合中(比如ArrayList),想办法把该电台覆盖的地区在下次比较时去掉
- 重复第1步直到覆盖了全部的地区
package algorithm.greedy;
import sun.jvm.hotspot.oops.BranchData;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
public class GreedyDemo {
public static void main(String[] args) {
// create radio, put into map
HashMap<String, HashSet<String>> broadcasts = new HashMap<>();
// put radio station into broadcasts
HashSet<String> hashSet1 = new HashSet<>();
hashSet1.add("beijing");
hashSet1.add("shanghai");
hashSet1.add("tianjin");
HashSet<String> hashSet2 = new HashSet<>();
hashSet2.add("guangzhou");
hashSet2.add("shanghai");
hashSet2.add("shenzhen");
HashSet<String> hashSet3 = new HashSet<>();
hashSet3.add("chengdu");
hashSet3.add("shanghai");
hashSet3.add("hangzhou");
HashSet<String> hashSet4 = new HashSet<>();
hashSet4.add("shanghai");
hashSet4.add("tianjin");
HashSet<String> hashSet5 = new HashSet<>();
hashSet5.add("hangzhou");
hashSet5.add("dalian");
// add to hashmap
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<>();
allAreas.add("beijing");
allAreas.add("shanghai");
allAreas.add("tianjin");
allAreas.add("guangzhou");
allAreas.add("shenzhen");
allAreas.add("chengdu");
allAreas.add("hangzhou");
allAreas.add("dalian");
// create ArrayList, store selected radio station
ArrayList<String> selects = new ArrayList<>();
// define a temp collection, storing intersect areas covered by radio station and not covered by station when traversal
HashSet<String> tempSet = new HashSet<>();
// define maxKey, key of station it can covered non-covered areas in a traversal
// if maxKey!=null, add to selects
String maxKey = null;
while(allAreas.size()!=0){ // if allAreas not 0, means it not covered all areas
// reset maxKey to 0 for each while loop
maxKey = null;
// traverse broadcasts, take out key
for(String key:broadcasts.keySet()){
// clear tempSet in each for loop
tempSet.clear();
// areas covered by current key
HashSet<String> areas = broadcasts.get(key);
tempSet.addAll(areas);
// get intersection of tempSet and allAreas
tempSet.retainAll(allAreas);
// if the number of covered areas in current set is bigger than
// areas pointed by maxKey
// reset maxKey
if(tempSet.size() > 0 && (maxKey == null || tempSet.size()>broadcasts.get(maxKey).size())){
maxKey = key;
}
}
// maxKey != null, add maxKey into selects
if(maxKey != null){
selects.add(maxKey);
// clear covered radio station pointed by maxKey from allAreas
allAreas.removeAll(broadcasts.get(maxKey));
}
}
System.out.println("result "+selects);
}
}