Java使用贪心算法解决电台覆盖问题(示例详解)
作者:CoderDreams 发布时间:2022-12-31 05:58:48
java使用贪心算法解决电台覆盖问题
代码实现
/**
* 贪心算法实现集合覆盖
*/
public class Demo {
public static void main(String[] args) {
// 创建电台和地区集合
HashMap<String, HashSet<String>> broadcasts = new HashMap<>();
// 创建各个电台
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);
// 建立各个地区的集合
HashSet<String> allAreas = new HashSet<>();
for (Map.Entry<String, HashSet<String>> entry : broadcasts.entrySet()) {
HashSet<String> value = entry.getValue();
allAreas.addAll(value);
}
// 创建选择的电台的集合
ArrayList<String> broadSelect = new ArrayList<>();
// 定义一个临时的集合
HashSet<String> tempSet = new HashSet<>();
// 定义一个指针,用于指向当前最优
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);
// 如果当前选择有覆盖地区
if (tempSet.size() > 0 &&
// 此时,如果maxKey还没有指向就指向
(maxKey == null ||
// 如果maxKey已经有指向就比较谁最优解
(tempSet.size() > (broadcasts.get(maxKey).size())))) {
maxKey = key;
}
}
if (maxKey != null) {
// 将maxKey加入
broadSelect.add(maxKey);
// 并将allAreas去掉maxKey能覆盖的地区
allAreas.removeAll(broadcasts.get(maxKey));
// 打印结果
System.out.println(broadSelect);
}
}
补充:下面看下贪心算法解决集合覆盖问题
贪心算法:指在对问题求解时,在每一步都选择最好的选择,从而希望得到最好的结果。
解决集合覆盖问题
比如有5个广播台,每个广播台覆盖的区域不一样,怎么选择最少的广播台,让所有区域都覆盖上
如 k1广播台覆盖的区域有:北京、上海、天津
k2广播台覆盖的区域有:北京、山东、深圳
k3广播台覆盖的区域有:成都、上海、杭州
k4广播台覆盖的区域有:上海、天津
k5广播台覆盖的区域有:杭州、武汉
步骤:
1. 遍历所有广播台,找到了个覆盖了最多未覆盖的地区的电台
2. 将这个电台加入到集合中,想办法将该电台覆盖的地区下次比较时去掉
3. 重复第1步,直到覆盖了全部区域
图解
所有区域:{北京、上海、天津、山东、深圳、成都、杭州、武汉};
选择的电台:{}
第一步:遍历所有广播台,找到了个覆盖了最多未覆盖的地区的电台
k1(北京、上海、天津),k2(北京、山东、深圳),k3(成都、上海、杭州)在所有区域({北京、上海、天津、山东、深圳、成都、杭州、武汉})中覆盖的个数为3
k4(上海、天津),k5(杭州、武汉)在在所有区域({北京、上海、天津、山东、深圳、成都、杭州、武汉})中覆盖的个数为2
选择最大覆盖数k1加入到选择的电台{k1},
第二步:将k1(北京、上海、天津)从所覆盖的区域从所有区域中移除,所有区域更新为:{山东、深圳、成都、杭州、武汉};
第三步:重复第一步,遍历所有广播
k1(北京、上海、天津)在所有区域({山东、深圳、成都、杭州、武汉})中覆盖的个数为0
k2(北京、山东、深圳)在所有区域({山东、深圳、成都、杭州、武汉})中覆盖的个数为2
k3(成都、上海、杭州)在所有区域({山东、深圳、成都、杭州、武汉})中覆盖的个数为2
k4(上海、天津)在所有区域({山东、深圳、成都、杭州、武汉})中覆盖的个数为0
k5(杭州、武汉)在所有区域({山东、深圳、成都、杭州、武汉})中覆盖的个数为2
选择最大覆盖数k2加入到选择的电台{k1,k2}
将k2(北京、山东、深圳)从所覆盖的区域从所有区域中移除,所有区域更新为:{成都、杭州、武汉};
k1(北京、上海、天津)在所有区域({成都、杭州、武汉})中覆盖的个数为0
k2(北京、山东、深圳)在所有区域({成都、杭州、武汉})中覆盖的个数为0
k3(成都、上海、杭州)在所有区域({成都、杭州、武汉})中覆盖的个数为2
k4(上海、天津)在所有区域({成都、杭州、武汉})中覆盖的个数为0
k5(杭州、武汉)在所有区域({成都、杭州、武汉})中覆盖的个数为2
选择最大覆盖数k3加入到选择的电台{k1,k2,k3}
将k3(成都、上海、杭州)从所覆盖的区域从所有区域中移除,所有区域更新为:{武汉};
k1(北京、上海、天津)在所有区域({成都、杭州、武汉})中覆盖的个数为0
k2(北京、山东、深圳)在所有区域({成都、杭州、武汉})中覆盖的个数为0
k3(成都、上海、杭州)在所有区域({成都、杭州、武汉})中覆盖的个数为0
k4(上海、天津)在所有区域({成都、杭州、武汉})中覆盖的个数为0
k5(杭州、武汉)在所有区域({成都、杭州、武汉})中覆盖的个数为1
选择最大覆盖数k5加入到选择的电台{k1,k2,k3,k5}
完成
代码实现:
package azhong.greedy_algo;
import java.util.*;
/**
* 贪心算法
* 在对问题求解时,在每一步都选择最好的选择,从而希望得到最好的结果。
*/
public class GreedyAlgoDemo {
public static void main(String[] args) {
//每个电台覆盖的区域
Map<String,HashSet<String>> allStations = initRadioStation();
//需要覆盖的所有区域
HashSet<String> allAreas = getAllAreas(allStations);
//存放选择的电台
List<String> selectedStations = new ArrayList<>();
while (allAreas.size()>0) {
//遍历所有广播台,找到了个覆盖了最多未覆盖的地区的电台
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();
//当前电台在所有区域覆盖的个数
int c = testIntersectionOfSet(values, allAreas);
System.out.println(k + " 在所有区域覆盖的个数: " + c);
if(c>maxIndex){
maxIndex=c;
maxK=k;
areaInMaxK=values;
}
}
if(maxK!=null){
//选择最大覆盖数k1加入到选择的电台{k1},
selectedStations.add(maxK);
//将k1(北京、上海、天津)从所覆盖的区域从所有区域中移除,所有区域更新为:{山东、深圳、成都、杭州、武汉};
allAreas.removeAll(areaInMaxK);
//重置,进入下一次循环
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广播台覆盖的区域有:北京、上海、天津
* k2广播台覆盖的区域有:北京、山东、深圳
* k3广播台覆盖的区域有:成都、上海、杭州
* k4广播台覆盖的区域有:上海、天津
* k5广播台覆盖的区域有:杭州、武汉
* @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 在所有区域覆盖的个数: 3
k2 在所有区域覆盖的个数: 3
k3 在所有区域覆盖的个数: 3
k4 在所有区域覆盖的个数: 2
k5 在所有区域覆盖的个数: 2
****************************
k1 在所有区域覆盖的个数: 0
k2 在所有区域覆盖的个数: 2
k3 在所有区域覆盖的个数: 2
k4 在所有区域覆盖的个数: 0
k5 在所有区域覆盖的个数: 2
****************************
k1 在所有区域覆盖的个数: 0
k2 在所有区域覆盖的个数: 0
k3 在所有区域覆盖的个数: 2
k4 在所有区域覆盖的个数: 0
k5 在所有区域覆盖的个数: 2
****************************
k1 在所有区域覆盖的个数: 0
k2 在所有区域覆盖的个数: 0
k3 在所有区域覆盖的个数: 0
k4 在所有区域覆盖的个数: 0
k5 在所有区域覆盖的个数: 1
****************************
[k1, k2, k3, k5]
来源:https://www.cnblogs.com/coderDreams/p/16188966.html


猜你喜欢
- 发现问题肯定有人发现连接mysql失败,然后又找不到问题所在,又出现一大最报错,如下图。解决过程 1.先查询自己的java版本,在
- 相信大家对SaaS架构都有所了解,这里也不过多介绍,让我们直奔主题。技术框架springboot版本为2.3.4.RELEASE持久层采用J
- 判断用户输入的是否至少含有N位小数。1.当用户输入的是非数字时抛出异常,返回false。2.当用户输入数字是,判断其数字是否至少含有N位小数
- 简介OCSP在线证书状态协议是为了替换CRL而提出来的。对于现代web服务器来说一般都是支持OCSP的,OCSP也是现代web服务器的标配。
- 查询数据会比较耗时,所以我们想把查询数据放在一个异步任务中,查询结果获得Cursor,然后在onPostExecute (Cursor re
- 目录开始准备开始动画画圆弧项目使用背景图完整代码今天介绍一个很简单的倒计时动画,仿酷狗音乐的启动页倒计时效果,也是大多数APP在用的一个动画
- 开始接触分布式概念,学习之前要准备搭建Dubbo和Zookeeper环境的简单搭建。Window下安装Zookeeper和Dubbo-adm
- 今天传图片,用的base64字符串,POST方法,前端传送的时候总是莫名其妙的崩溃,去网上搜了半天,以为是文件大小被限制了,但是我这个是字符
- 在第一次启动项目的时候,由于使用了RabbitMQ的默认guest账号,怎么也登不进去,后来还是在Admin重新创建了一个其他的账号,然后开
- 之前文章介绍过了Fluent基本框架等,其中有几个重要的方法用到了IQuery和IUpdate对象。 这2个对象是FluentMybatis
- 1. 概述官方JavaDocsApi: javax.swing.JProgressBar JProgressBar,进度条。以可视化形式显示
- 本文实例为大家分享了Android弹窗控件CustomFiltControl的使用方法,供大家参考,具体内容如下效果:起初踩的坑:&nbs
- Spring Boot CLI是Spring Boot项目提供的一个用于快速运行Spring Boot应用的命令行工具,通过结合Groovy
- 目录“头疼”“吃药”工具代码使用代码“头疼”自己在用Angular做项目时,前端要请求后端数据时的代码如下this.http.get(&qu
- 引言之前关于事务的文章已介绍了事务的概念以及事务的四个属性(ACID),相信你对事务应该有所认识和了解。本篇文章是关于事务的隔离性,介绍数据
- 经常会遇到这样的情况,我们在响应客户端请求的数据的时候需要对数据进行处理,比如数据库中的数据是int型,它可能表示某个枚举,或者其它的逻辑意
- 本文实例讲述了C#实现XML与实体类之间相互转换的方法。分享给大家供大家参考,具体如下:using System;using System.
- 一、问题描述LBS位置服务是android应用中重要的功能,应用越来越广泛,下面我们逐步学习和实现lbs相关的应用如定位、地图、导航等,首先
- 今天聊一个小伙伴在星球上的提问:问题不难,解决方案也有很多,因此我决定撸一篇文章和大家仔细说说这个问题。1. 配置文件位置首先小伙伴们要明白
- 一、需求有时候应用需要在内部切换语言但又不影响系统的语言,比如是应用现在是中文的,系统语言也是中文的,我把应用的切换成英文显示后系统语言还是