Java使用貪心算法解決電臺(tái)覆蓋問(wèn)題(示例詳解)
java使用貪心算法解決電臺(tái)覆蓋問(wèn)題
代碼實(shí)現(xiàn)
/** * 貪心算法實(shí)現(xiàn)集合覆蓋 */ public class Demo { public static void main(String[] args) { // 創(chuàng)建電臺(tái)和地區(qū)集合 HashMap<String, HashSet<String>> broadcasts = new HashMap<>(); // 創(chuàng)建各個(gè)電臺(tái) HashSet<String> k1 = new HashSet<>(); k1.add("北京"); k1.add("上海"); k1.add("天津"); HashSet<String> k2 = new HashSet<>(); k2.add("廣州"); k2.add("北京"); k2.add("深圳"); HashSet<String> k3 = new HashSet<>(); k3.add("成都"); k3.add("上海"); k3.add("杭州"); HashSet<String> k4 = new HashSet<>(); k4.add("上海"); k4.add("天津"); HashSet<String> k5 = new HashSet<>(); k5.add("杭州"); k5.add("大連"); // 加入各個(gè)電臺(tái) broadcasts.put("k1", k1); broadcasts.put("k2", k2); broadcasts.put("k3", k3); broadcasts.put("k4", k4); broadcasts.put("k5", k5); // 建立各個(gè)地區(qū)的集合 HashSet<String> allAreas = new HashSet<>(); for (Map.Entry<String, HashSet<String>> entry : broadcasts.entrySet()) { HashSet<String> value = entry.getValue(); allAreas.addAll(value); } // 創(chuàng)建選擇的電臺(tái)的集合 ArrayList<String> broadSelect = new ArrayList<>(); // 定義一個(gè)臨時(shí)的集合 HashSet<String> tempSet = new HashSet<>(); // 定義一個(gè)指針,用于指向當(dāng)前最優(yōu) String maxKey = null; while (allAreas.size() > 0) { // 重置置空 maxKey = null; // 遍歷 for (String key : broadcasts.keySet()) { // 重置置空 tempSet.clear(); HashSet<String> value = broadcasts.get(key); tempSet.addAll(value); // 求出temp和allAreas的交集 tempSet.retainAll(allAreas); // 如果當(dāng)前選擇有覆蓋地區(qū) if (tempSet.size() > 0 && // 此時(shí),如果maxKey還沒(méi)有指向就指向 (maxKey == null || // 如果maxKey已經(jīng)有指向就比較誰(shuí)最優(yōu)解 (tempSet.size() > (broadcasts.get(maxKey).size())))) { maxKey = key; } } if (maxKey != null) { // 將maxKey加入 broadSelect.add(maxKey); // 并將allAreas去掉maxKey能覆蓋的地區(qū) allAreas.removeAll(broadcasts.get(maxKey)); // 打印結(jié)果 System.out.println(broadSelect); } }
補(bǔ)充:下面看下貪心算法解決集合覆蓋問(wèn)題
貪心算法:指在對(duì)問(wèn)題求解時(shí),在每一步都選擇最好的選擇,從而希望得到最好的結(jié)果。
解決集合覆蓋問(wèn)題
比如有5個(gè)廣播臺(tái),每個(gè)廣播臺(tái)覆蓋的區(qū)域不一樣,怎么選擇最少的廣播臺(tái),讓所有區(qū)域都覆蓋上
如 k1廣播臺(tái)覆蓋的區(qū)域有:北京、上海、天津
k2廣播臺(tái)覆蓋的區(qū)域有:北京、山東、深圳
k3廣播臺(tái)覆蓋的區(qū)域有:成都、上海、杭州
k4廣播臺(tái)覆蓋的區(qū)域有:上海、天津
k5廣播臺(tái)覆蓋的區(qū)域有:杭州、武漢
步驟:
1. 遍歷所有廣播臺(tái),找到了個(gè)覆蓋了最多未覆蓋的地區(qū)的電臺(tái)
2. 將這個(gè)電臺(tái)加入到集合中,想辦法將該電臺(tái)覆蓋的地區(qū)下次比較時(shí)去掉
3. 重復(fù)第1步,直到覆蓋了全部區(qū)域
圖解
所有區(qū)域:{北京、上海、天津、山東、深圳、成都、杭州、武漢};
選擇的電臺(tái):{}
第一步:遍歷所有廣播臺(tái),找到了個(gè)覆蓋了最多未覆蓋的地區(qū)的電臺(tái)
k1(北京、上海、天津),k2(北京、山東、深圳),k3(成都、上海、杭州)在所有區(qū)域({北京、上海、天津、山東、深圳、成都、杭州、武漢})中覆蓋的個(gè)數(shù)為3
k4(上海、天津),k5(杭州、武漢)在在所有區(qū)域({北京、上海、天津、山東、深圳、成都、杭州、武漢})中覆蓋的個(gè)數(shù)為2
選擇最大覆蓋數(shù)k1加入到選擇的電臺(tái){k1},
第二步:將k1(北京、上海、天津)從所覆蓋的區(qū)域從所有區(qū)域中移除,所有區(qū)域更新為:{山東、深圳、成都、杭州、武漢};
第三步:重復(fù)第一步,遍歷所有廣播
k1(北京、上海、天津)在所有區(qū)域({山東、深圳、成都、杭州、武漢})中覆蓋的個(gè)數(shù)為0
k2(北京、山東、深圳)在所有區(qū)域({山東、深圳、成都、杭州、武漢})中覆蓋的個(gè)數(shù)為2
k3(成都、上海、杭州)在所有區(qū)域({山東、深圳、成都、杭州、武漢})中覆蓋的個(gè)數(shù)為2
k4(上海、天津)在所有區(qū)域({山東、深圳、成都、杭州、武漢})中覆蓋的個(gè)數(shù)為0
k5(杭州、武漢)在所有區(qū)域({山東、深圳、成都、杭州、武漢})中覆蓋的個(gè)數(shù)為2
選擇最大覆蓋數(shù)k2加入到選擇的電臺(tái){k1,k2}
將k2(北京、山東、深圳)從所覆蓋的區(qū)域從所有區(qū)域中移除,所有區(qū)域更新為:{成都、杭州、武漢};
k1(北京、上海、天津)在所有區(qū)域({成都、杭州、武漢})中覆蓋的個(gè)數(shù)為0
k2(北京、山東、深圳)在所有區(qū)域({成都、杭州、武漢})中覆蓋的個(gè)數(shù)為0
k3(成都、上海、杭州)在所有區(qū)域({成都、杭州、武漢})中覆蓋的個(gè)數(shù)為2
k4(上海、天津)在所有區(qū)域({成都、杭州、武漢})中覆蓋的個(gè)數(shù)為0
k5(杭州、武漢)在所有區(qū)域({成都、杭州、武漢})中覆蓋的個(gè)數(shù)為2
選擇最大覆蓋數(shù)k3加入到選擇的電臺(tái){k1,k2,k3}
將k3(成都、上海、杭州)從所覆蓋的區(qū)域從所有區(qū)域中移除,所有區(qū)域更新為:{武漢};
k1(北京、上海、天津)在所有區(qū)域({成都、杭州、武漢})中覆蓋的個(gè)數(shù)為0
k2(北京、山東、深圳)在所有區(qū)域({成都、杭州、武漢})中覆蓋的個(gè)數(shù)為0
k3(成都、上海、杭州)在所有區(qū)域({成都、杭州、武漢})中覆蓋的個(gè)數(shù)為0
k4(上海、天津)在所有區(qū)域({成都、杭州、武漢})中覆蓋的個(gè)數(shù)為0
k5(杭州、武漢)在所有區(qū)域({成都、杭州、武漢})中覆蓋的個(gè)數(shù)為1
選擇最大覆蓋數(shù)k5加入到選擇的電臺(tái){k1,k2,k3,k5}
完成
代碼實(shí)現(xiàn):
package azhong.greedy_algo; import java.util.*; /** * 貪心算法 * 在對(duì)問(wèn)題求解時(shí),在每一步都選擇最好的選擇,從而希望得到最好的結(jié)果。 */ public class GreedyAlgoDemo { public static void main(String[] args) { //每個(gè)電臺(tái)覆蓋的區(qū)域 Map<String,HashSet<String>> allStations = initRadioStation(); //需要覆蓋的所有區(qū)域 HashSet<String> allAreas = getAllAreas(allStations); //存放選擇的電臺(tái) List<String> selectedStations = new ArrayList<>(); while (allAreas.size()>0) { //遍歷所有廣播臺(tái),找到了個(gè)覆蓋了最多未覆蓋的地區(qū)的電臺(tái) int maxIndex=0; String maxK=null; HashSet<String> areaInMaxK=null; for (Map.Entry<String, HashSet<String>> entry : allStations.entrySet()) { final String k = entry.getKey(); HashSet<String> values = entry.getValue(); //當(dāng)前電臺(tái)在所有區(qū)域覆蓋的個(gè)數(shù) int c = testIntersectionOfSet(values, allAreas); System.out.println(k + " 在所有區(qū)域覆蓋的個(gè)數(shù): " + c); if(c>maxIndex){ maxIndex=c; maxK=k; areaInMaxK=values; } } if(maxK!=null){ //選擇最大覆蓋數(shù)k1加入到選擇的電臺(tái){k1}, selectedStations.add(maxK); //將k1(北京、上海、天津)從所覆蓋的區(qū)域從所有區(qū)域中移除,所有區(qū)域更新為:{山東、深圳、成都、杭州、武漢}; allAreas.removeAll(areaInMaxK); //重置,進(jìn)入下一次循環(huán) maxIndex=0; maxK=null; areaInMaxK=null; System.out.println("****************************"); } System.out.println(selectedStations); } /** * 測(cè)試:求兩個(gè)集合的交集 * A{北京、上海、天津} * B{北京、上海、天津、山東、深圳、成都、杭州、武漢} * A.retainAll(B); 得到A{北京、上海、天津} 個(gè)數(shù)為3 */ private static int testIntersectionOfSet(HashSet A,HashSet B){ //將存在于集合A中但不存在于集合B中的元素移除。 A.retainAll(B); return A.size(); * 初始化電臺(tái) * k1廣播臺(tái)覆蓋的區(qū)域有:北京、上海、天津 * k2廣播臺(tái)覆蓋的區(qū)域有:北京、山東、深圳 * k3廣播臺(tái)覆蓋的區(qū)域有:成都、上海、杭州 * k4廣播臺(tái)覆蓋的區(qū)域有:上海、天津 * k5廣播臺(tái)覆蓋的區(qū)域有:杭州、武漢 * @return Map<String,HashSet<String>>類型電臺(tái)集合 private static Map<String,HashSet<String>> initRadioStation(){ Map<String,HashSet<String>> allStations = new HashMap<String,HashSet<String>>(); HashSet<String> k1 = new HashSet<>(); k1.add("北京"); k1.add("上海"); k1.add("天津"); HashSet<String> k2 = new HashSet<>(); k2.add("北京"); k2.add("山東"); k2.add("深圳"); HashSet<String> k3 = new HashSet<>(); k3.add("成都"); k3.add("上海"); k3.add("杭州"); HashSet<String> k4 = new HashSet<>(); k4.add("上海"); k4.add("天津"); HashSet<String> k5 = new HashSet<>(); k5.add("杭州"); k5.add("武漢"); allStations.put("k1",k1); allStations.put("k2",k2); allStations.put("k3",k3); allStations.put("k4",k4); allStations.put("k5",k5); return allStations; private static HashSet<String> getAllAreas(Map<String,HashSet<String>> allStations){ HashSet<String> allAreas = new HashSet<>(); Collection<HashSet<String>> stations = allStations.values(); for(HashSet<String> station:stations){ Iterator<String> areas = station.iterator(); //操泥瑪,寫成了if while (areas.hasNext()){ allAreas.add(areas.next()); return allAreas; }
運(yùn)行結(jié)果為:
k1 在所有區(qū)域覆蓋的個(gè)數(shù): 3
k2 在所有區(qū)域覆蓋的個(gè)數(shù): 3
k3 在所有區(qū)域覆蓋的個(gè)數(shù): 3
k4 在所有區(qū)域覆蓋的個(gè)數(shù): 2
k5 在所有區(qū)域覆蓋的個(gè)數(shù): 2
****************************
k1 在所有區(qū)域覆蓋的個(gè)數(shù): 0
k2 在所有區(qū)域覆蓋的個(gè)數(shù): 2
k3 在所有區(qū)域覆蓋的個(gè)數(shù): 2
k4 在所有區(qū)域覆蓋的個(gè)數(shù): 0
k5 在所有區(qū)域覆蓋的個(gè)數(shù): 2
****************************
k1 在所有區(qū)域覆蓋的個(gè)數(shù): 0
k2 在所有區(qū)域覆蓋的個(gè)數(shù): 0
k3 在所有區(qū)域覆蓋的個(gè)數(shù): 2
k4 在所有區(qū)域覆蓋的個(gè)數(shù): 0
k5 在所有區(qū)域覆蓋的個(gè)數(shù): 2
****************************
k1 在所有區(qū)域覆蓋的個(gè)數(shù): 0
k2 在所有區(qū)域覆蓋的個(gè)數(shù): 0
k3 在所有區(qū)域覆蓋的個(gè)數(shù): 0
k4 在所有區(qū)域覆蓋的個(gè)數(shù): 0
k5 在所有區(qū)域覆蓋的個(gè)數(shù): 1
****************************
[k1, k2, k3, k5]
到此這篇關(guān)于Java使用貪心算法解決電臺(tái)覆蓋問(wèn)題的文章就介紹到這了,更多相關(guān)java貪心算法內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
java發(fā)起http請(qǐng)求獲取返回的Json對(duì)象方法
下面小編就為大家分享一篇java發(fā)起http請(qǐng)求獲取返回的Json對(duì)象方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2018-03-03Maven Spring jar包啟動(dòng)報(bào)錯(cuò)問(wèn)題解決方案
maven 編譯jar包,放在linux服務(wù)器啟動(dòng)不起來(lái),提示:xxxx-0.0.1-SNAPSHOT.jar中沒(méi)有主清單屬性,接下來(lái)通過(guò)本文給大家分享問(wèn)題原因及解決方案,感興趣的朋友跟隨小編一起看看吧2023-10-10Springboot前后端分離項(xiàng)目配置跨域?qū)崿F(xiàn)過(guò)程解析
這篇文章主要介紹了Springboot前后端分離項(xiàng)目配置跨域?qū)崿F(xiàn)過(guò)程解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-08-08Java中垃圾回收器GC對(duì)吞吐量的影響測(cè)試
這篇文章主要介紹了Java中垃圾回收器GC對(duì)吞吐量的影響測(cè)試,本文算是一個(gè)對(duì)垃圾回收器GC的優(yōu)化文章,需要的朋友可以參考下2014-09-09