Java使用貪心算法解決電臺覆蓋問題(示例詳解)
java使用貪心算法解決電臺覆蓋問題
代碼實現
/**
* 貪心算法實現集合覆蓋
*/
public class Demo {
public static void main(String[] args) {
// 創(chuàng)建電臺和地區(qū)集合
HashMap<String, HashSet<String>> broadcasts = new HashMap<>();
// 創(chuàng)建各個電臺
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("大連");
// 加入各個電臺
broadcasts.put("k1", k1);
broadcasts.put("k2", k2);
broadcasts.put("k3", k3);
broadcasts.put("k4", k4);
broadcasts.put("k5", k5);
// 建立各個地區(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)建選擇的電臺的集合
ArrayList<String> broadSelect = new ArrayList<>();
// 定義一個臨時的集合
HashSet<String> tempSet = new HashSet<>();
// 定義一個指針,用于指向當前最優(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);
// 如果當前選擇有覆蓋地區(qū)
if (tempSet.size() > 0 &&
// 此時,如果maxKey還沒有指向就指向
(maxKey == null ||
// 如果maxKey已經有指向就比較誰最優(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));
// 打印結果
System.out.println(broadSelect);
}
}補充:下面看下貪心算法解決集合覆蓋問題
貪心算法:指在對問題求解時,在每一步都選擇最好的選擇,從而希望得到最好的結果。
解決集合覆蓋問題
比如有5個廣播臺,每個廣播臺覆蓋的區(qū)域不一樣,怎么選擇最少的廣播臺,讓所有區(qū)域都覆蓋上
如 k1廣播臺覆蓋的區(qū)域有:北京、上海、天津
k2廣播臺覆蓋的區(qū)域有:北京、山東、深圳
k3廣播臺覆蓋的區(qū)域有:成都、上海、杭州
k4廣播臺覆蓋的區(qū)域有:上海、天津
k5廣播臺覆蓋的區(qū)域有:杭州、武漢
步驟:
1. 遍歷所有廣播臺,找到了個覆蓋了最多未覆蓋的地區(qū)的電臺
2. 將這個電臺加入到集合中,想辦法將該電臺覆蓋的地區(qū)下次比較時去掉
3. 重復第1步,直到覆蓋了全部區(qū)域
圖解
所有區(qū)域:{北京、上海、天津、山東、深圳、成都、杭州、武漢};
選擇的電臺:{}
第一步:遍歷所有廣播臺,找到了個覆蓋了最多未覆蓋的地區(qū)的電臺
k1(北京、上海、天津),k2(北京、山東、深圳),k3(成都、上海、杭州)在所有區(qū)域({北京、上海、天津、山東、深圳、成都、杭州、武漢})中覆蓋的個數為3
k4(上海、天津),k5(杭州、武漢)在在所有區(qū)域({北京、上海、天津、山東、深圳、成都、杭州、武漢})中覆蓋的個數為2
選擇最大覆蓋數k1加入到選擇的電臺{k1},
第二步:將k1(北京、上海、天津)從所覆蓋的區(qū)域從所有區(qū)域中移除,所有區(qū)域更新為:{山東、深圳、成都、杭州、武漢};
第三步:重復第一步,遍歷所有廣播
k1(北京、上海、天津)在所有區(qū)域({山東、深圳、成都、杭州、武漢})中覆蓋的個數為0
k2(北京、山東、深圳)在所有區(qū)域({山東、深圳、成都、杭州、武漢})中覆蓋的個數為2
k3(成都、上海、杭州)在所有區(qū)域({山東、深圳、成都、杭州、武漢})中覆蓋的個數為2
k4(上海、天津)在所有區(qū)域({山東、深圳、成都、杭州、武漢})中覆蓋的個數為0
k5(杭州、武漢)在所有區(qū)域({山東、深圳、成都、杭州、武漢})中覆蓋的個數為2
選擇最大覆蓋數k2加入到選擇的電臺{k1,k2}
將k2(北京、山東、深圳)從所覆蓋的區(qū)域從所有區(qū)域中移除,所有區(qū)域更新為:{成都、杭州、武漢};
k1(北京、上海、天津)在所有區(qū)域({成都、杭州、武漢})中覆蓋的個數為0
k2(北京、山東、深圳)在所有區(qū)域({成都、杭州、武漢})中覆蓋的個數為0
k3(成都、上海、杭州)在所有區(qū)域({成都、杭州、武漢})中覆蓋的個數為2
k4(上海、天津)在所有區(qū)域({成都、杭州、武漢})中覆蓋的個數為0
k5(杭州、武漢)在所有區(qū)域({成都、杭州、武漢})中覆蓋的個數為2
選擇最大覆蓋數k3加入到選擇的電臺{k1,k2,k3}
將k3(成都、上海、杭州)從所覆蓋的區(qū)域從所有區(qū)域中移除,所有區(qū)域更新為:{武漢};
k1(北京、上海、天津)在所有區(qū)域({成都、杭州、武漢})中覆蓋的個數為0
k2(北京、山東、深圳)在所有區(qū)域({成都、杭州、武漢})中覆蓋的個數為0
k3(成都、上海、杭州)在所有區(qū)域({成都、杭州、武漢})中覆蓋的個數為0
k4(上海、天津)在所有區(qū)域({成都、杭州、武漢})中覆蓋的個數為0
k5(杭州、武漢)在所有區(qū)域({成都、杭州、武漢})中覆蓋的個數為1
選擇最大覆蓋數k5加入到選擇的電臺{k1,k2,k3,k5}
完成
代碼實現:
package azhong.greedy_algo;
import java.util.*;
/**
* 貪心算法
* 在對問題求解時,在每一步都選擇最好的選擇,從而希望得到最好的結果。
*/
public class GreedyAlgoDemo {
public static void main(String[] args) {
//每個電臺覆蓋的區(qū)域
Map<String,HashSet<String>> allStations = initRadioStation();
//需要覆蓋的所有區(qū)域
HashSet<String> allAreas = getAllAreas(allStations);
//存放選擇的電臺
List<String> selectedStations = new ArrayList<>();
while (allAreas.size()>0) {
//遍歷所有廣播臺,找到了個覆蓋了最多未覆蓋的地區(qū)的電臺
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();
//當前電臺在所有區(qū)域覆蓋的個數
int c = testIntersectionOfSet(values, allAreas);
System.out.println(k + " 在所有區(qū)域覆蓋的個數: " + c);
if(c>maxIndex){
maxIndex=c;
maxK=k;
areaInMaxK=values;
}
}
if(maxK!=null){
//選擇最大覆蓋數k1加入到選擇的電臺{k1},
selectedStations.add(maxK);
//將k1(北京、上海、天津)從所覆蓋的區(qū)域從所有區(qū)域中移除,所有區(qū)域更新為:{山東、深圳、成都、杭州、武漢};
allAreas.removeAll(areaInMaxK);
//重置,進入下一次循環(huán)
maxIndex=0;
maxK=null;
areaInMaxK=null;
System.out.println("****************************");
}
System.out.println(selectedStations);
}
/**
* 測試:求兩個集合的交集
* A{北京、上海、天津}
* B{北京、上海、天津、山東、深圳、成都、杭州、武漢}
* A.retainAll(B); 得到A{北京、上海、天津} 個數為3
*/
private static int testIntersectionOfSet(HashSet A,HashSet B){
//將存在于集合A中但不存在于集合B中的元素移除。
A.retainAll(B);
return A.size();
* 初始化電臺
* k1廣播臺覆蓋的區(qū)域有:北京、上海、天津
* k2廣播臺覆蓋的區(qū)域有:北京、山東、深圳
* k3廣播臺覆蓋的區(qū)域有:成都、上海、杭州
* k4廣播臺覆蓋的區(qū)域有:上海、天津
* k5廣播臺覆蓋的區(qū)域有:杭州、武漢
* @return Map<String,HashSet<String>>類型電臺集合
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;
}運行結果為:
k1 在所有區(qū)域覆蓋的個數: 3
k2 在所有區(qū)域覆蓋的個數: 3
k3 在所有區(qū)域覆蓋的個數: 3
k4 在所有區(qū)域覆蓋的個數: 2
k5 在所有區(qū)域覆蓋的個數: 2
****************************
k1 在所有區(qū)域覆蓋的個數: 0
k2 在所有區(qū)域覆蓋的個數: 2
k3 在所有區(qū)域覆蓋的個數: 2
k4 在所有區(qū)域覆蓋的個數: 0
k5 在所有區(qū)域覆蓋的個數: 2
****************************
k1 在所有區(qū)域覆蓋的個數: 0
k2 在所有區(qū)域覆蓋的個數: 0
k3 在所有區(qū)域覆蓋的個數: 2
k4 在所有區(qū)域覆蓋的個數: 0
k5 在所有區(qū)域覆蓋的個數: 2
****************************
k1 在所有區(qū)域覆蓋的個數: 0
k2 在所有區(qū)域覆蓋的個數: 0
k3 在所有區(qū)域覆蓋的個數: 0
k4 在所有區(qū)域覆蓋的個數: 0
k5 在所有區(qū)域覆蓋的個數: 1
****************************
[k1, k2, k3, k5]
到此這篇關于Java使用貪心算法解決電臺覆蓋問題的文章就介紹到這了,更多相關java貪心算法內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

