集合覆蓋問題、旅行商問題等都屬於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);
}
}
複製代碼