集合覆盖问题、旅行商问题等都属于NP完全问题,在数学领域上并没有快速得到最优解的方案,非常适合用贪婪算法。
判断方法:1.元素较少时,一般运行速度很快,但随着元素数量增多,速度会变得非常慢 2.涉及到需要计算比较"所有的组合"情况的通常是NP完全问题 3.无法分割成小问题,必须考虑各种可能的情况。这可能是NP完全问题 4.如果问题涉及序列(如旅行商问题中的城市序列)且难以解决,它可能就是NP完全问题 5.如果问题涉及集合(如广播台集合)且难以解决,它可能就是NP完全问题 6.如果问题可转换为集合覆盖问题或旅行商问题,那它肯定是NP完全问题
总结:
1.贪婪算法可以寻找局部最优解,并尝试与这种方式获得全局最优解
2.得到的可能是近似最优解,但也可能便是最优解(区间调度问题,最短路径问题(广度优先、狄克斯特拉))
3.对于完全NP问题,目前并没有快速得到最优解的解决方案
4.面临NP完全问题,最佳的做法就是使用近似算法
5.贪婪算法(近似算法)在大部分情况下易于实现,并且效率不错
例题:
1.选择和目标覆盖城市交集最多的电台
2. 去除交集后生成新的目标覆盖城市,再重新进行1
/**
* 贪婪算法 - 集合覆盖问题
* @author Administrator
*
*/
public class Greedy {
public static void main(String[] args){
//初始化广播台信息
HashMap<String,HashSet<String>> broadcasts = new HashMap<String,HashSet<String>>();
broadcasts.put("K1", new HashSet(Arrays.asList(new String[] {"ID","NV","UT"})));
broadcasts.put("K2", new HashSet(Arrays.asList(new String[] {"WA","ID","MT"})));
broadcasts.put("K3", new HashSet(Arrays.asList(new String[] {"OR","NV","CA"})));
broadcasts.put("K4", new HashSet(Arrays.asList(new String[] {"NV","UT"})));
broadcasts.put("K5", new HashSet(Arrays.asList(new String[] {"CA","AZ"})));
//需要覆盖的全部地区
HashSet<String> allAreas = new HashSet(Arrays.asList(new String[] {"ID","NV","UT","WA","MT","OR","CA","AZ"}));
//所选择的广播台列表
List<String> selects = new ArrayList<String>();
HashSet<String> tempSet = new HashSet<String>();
String maxKey = null;
while(allAreas.size()!=0) {
maxKey = null;
for(String key : broadcasts.keySet()) {
tempSet.clear();
HashSet<String> areas = broadcasts.get(key);
tempSet.addAll(areas);
//求出2个集合的交集,此时tempSet会被赋值为交集的内容,所以使用临时变量
tempSet.retainAll(allAreas);
//如果该集合包含的地区数量比原本的集合多
if (tempSet.size()>0 && (maxKey == null || tempSet.size() > broadcasts.get(maxKey).size())) {
maxKey = key;
}
}
if (maxKey != null) {
selects.add(maxKey);
allAreas.removeAll(broadcasts.get(maxKey));
}
}
System.out.print("selects:" + selects);
}
}
复制代码