问题描述

假设海岸线是一条无限延伸的直线,陆地在海岸线的一侧,海洋在另外一侧。每个小岛相当于海洋侧的一个点。坐落在海岸线上的基站只能覆盖半径为d的范围。应用直角坐标系,将海岸线作为x轴,设海洋侧在x轴上方。给定海洋中各小岛的位置,以及通信基站的覆盖半径,要求用最少的基站覆盖所有小岛,使得每个小岛都能和陆地通过某基站通信(在某个基站覆盖范围内)。
输入:小岛数目,基站覆盖半径,各小岛坐标
输出:覆盖小岛的最少基站数目及基站坐标,如果无解,输出-1.

问题分析

因为每一个基站点都在x坐标上,每个基站的通信覆盖区域都为固定半径的圆,所以容易知道y坐标绝对值小于该固定半径的小岛一定能被覆盖。
而要想实现用最少的基站(最少的圆)覆盖这些小岛,即基站覆盖的小岛数要尽量多,没有多余的基站,容易想到该问题与最少线段覆盖点非常类似,只是最少线段覆盖点问题是一维的,而最少圆覆盖是二维的,但贪心求解原理都相同。都是将小岛坐标从左至右(或从右至左)排列,逐一画圆并判断覆盖区域范围,但是最少圆覆盖问题的排序,应该是以小岛坐标为圆上一点时能覆盖的左区间从左至右排序更为准确。
如上图,输入小岛坐标S=[S2,S1,S4,S3],按照以各点为圆上一点时能覆盖的左区间从左至右(从小到大)排序后得到S=[S1,S2,S3,S4]。开始作圆,
从左至右,从S1开始,即先画出黄圈,到S2,因为S2在上一圆内,故继续;到S3,因S3在上一圆(黄圈)外,故保留上一圆(黄圈),另作新圆(蓝圈),到S4,因S4在上一圆(蓝圈)内,故继续。
否则,如果只是按照x坐标从左至右排序,即从S2开始作圆,到S1,S1并不在S2所作的红圈内,故作新圆,如此产生多余的圆。

求解思路

以各小岛坐标为半径为d的圆上一点时能覆盖的左区间,按从小到大排序得S集合,从S中依次考察点S[i]的位置,若S[i]不在上一圆C[j]内,则以该坐标为圆上一点、d为半径作新圆C[j+1],直到S中所有坐标考察完为止。
方法:

  1. if 输入的纵坐标大于基站半径d
  2. then return -1 exit
  3. else 按各坐标的左区间从小到大排序得S
  4. C[0]= X0 + sqrt(d * d – Y0 * Y0);
  5. for i←1 to n do
  6. if S[i]不在圆内
  7. then c = S[i].x + sqrt(d * d – S[i].y * S[i].y);
  8. then C←C∪{c}
  9. return C

算法正确性证明

(自己写的可能不太准确)
命题:对输入任何规模为n的输入实例,算法得到最少基站数;
归纳基础:证明对任何只有1个小岛(纵坐标小于基站半径)的输入实例,贪心法得到最优解,S中只有一个岛,则C中只有一个基站,最少基站集合就是C,显然正确;
归纳步骤:证明:假设对于任何n个小岛的输入实例贪心法都能得到最优解,那么对于任何n+1个小岛的输入实例,贪心法也得到最优解;
考虑输入N={1,2,…,n+1},已排序
由归纳假设,对于N’={2,3,…,n+1},
贪心法得到最优解I’,另I=I’∪{1}({1}表示只覆盖第1个小岛的基站)
若不然,存在包含1的关于N的最优解I^(1表示达到最左区间的坐标),且|I |>|I|;那么I*-{1}是N’和C’的解且|I^*-{1}|>|I-{1}|=|I’|,与I’是关于N’和C’的最优解矛盾。

复杂性计算

排序算法执行O(n log⁡n))次,贪心算法执行O(n)时间,总的算法时间T(n)=O(n log⁡n )

结果测试


编程实现

(如有错误欢迎指正!)
其中小岛坐标的排序参考了别人用Comparable接口实现Array排序的方法,没有手写排序算法。

package minCirlcle;
import java.util.Arrays;
import java.util.Scanner;class S2 implements Comparable<S2> { //小岛坐标及左区间private int x;private int y;private double left;public S2(int x, int y, double left) {this.setX(x);this.setY(y);this.setLeft(left);}public int compareTo(S2 s) {return (int) (this.getLeft() - s.left);}public int getX() {return x;}public void setX(int x) {this.x = x;}public int getY() {return y;}public void setY(int y) {this.y = y;}public double getLeft() {return left;}public void setLeft(double left) {this.left = left;}
}
class S22 {//基站坐标private double x;private int y;public S22(double x, int y) {this.setX(x);this.setY(y);}public double getX() {return x;}public void setX(double x) {this.x = x;}public int getY() {return y;}public void setY(int y) {this.y = y;}
}
class verify1{  //合理性检验private double tempC;private int tempX;private int tempY;private double tempD;private int flag;private int flagVer;public verify1(S2 S[],S22 C[],int d,int n,int m) {for(int i=0;i<n;i++) {tempX = S[i].getX();tempY = S[i].getY();flag = 0;for(int j=0;j<=m;j++) {tempC=C[j].getX();tempD=Math.sqrt((tempY * tempY + Math.pow((tempX - tempC), 2)));if(tempD>d) {flag = 0;}else{flag = 1;break;}}flagVer = flag + flagVer;}System.out.println("合理性验证结束");if(flagVer==n) {System.out.println("基站点能够覆盖所有岛屿");}else {System.out.println("基站点不能覆盖所有岛屿,请检查算法");}}
}public class IPDMinCircle {private static int n; // 岛数private int m; // 基站数public S22 C[] = new S22[n]; // 基站坐标private double c; // 基站横坐标private static int d; // 基站半径private int X1;private int Y1;private int tempX;private int tempY;private double tempD; // 小岛和旧圆心的距离public static int flag;public IPDMinCircle(S2 S[],int n,int d) {    X1 = S[0].getX();Y1 = S[0].getY();c = X1 + Math.sqrt(d * d - Y1 * Y1);C[0] = new S22(c,0);for (int j = 0; j < n; j++) {tempX = S[j].getX();tempY = S[j].getY();tempD = Math.sqrt((tempY * tempY + Math.pow((tempX - c), 2))); // 上一圆心位置,判断该岛坐标是否在上一圆内if ((tempD <= d)) { // 新岛坐标在旧圆内,即该岛位于旧圆内或圆上任意位置// 保留旧圆,不作新圆continue;} else if ((tempD > d)) { // 新岛坐标在旧圆外,即该岛位于旧圆心的右边且在圆外// 保留旧圆,另作新圆c = tempX + Math.sqrt(d * d - tempY * tempY);m = m + 1;C[m] = new S22(c,0);}}System.out.println(m+1);for (int i = 0; i <= m; i++) {System.out.println(C[i].getX() + " " + C[i].getY());}new verify1(S,C,d,n,m);}public static void main(String args[]) {Scanner in = new Scanner(System.in);System.out.println("请输入小岛数:");n = in.nextInt();System.out.println("请输入 基站半径:");d = in.nextInt();S2 S[] = new S2[n];System.out.println("请输入小岛坐标:");for (int i = 0; i < n; i++) {int k1 = in.nextInt();int k2 = in.nextInt();double tleft = Math.sqrt(d * d - k2 * k2) + k1 - d; S[i] = new S2(k1, k2, tleft);}for (int i = 0; i < n; i++) {if (Math.abs(S[i].getY()) > d) {flag = -1;System.out.println(flag);} else {flag = 1;}}if (flag > 0) {Arrays.sort(S, 0, n); // 排n个数,Arrays.sort(d)则默认排全部
//          for (int i = 0; i < n; i++) { //debug
//              System.out.println(S[i].getX()+" "+S[i].getY());
//          }new IPDMinCircle(S,n,d);}}
}

最少圆覆盖通信覆盖问题-算法分析设计-贪心算法-java实现相关推荐

  1. 算法分析与设计 —— 贪心算法「活动安排」「背包问题」「哈夫曼编码」

  2. 基于哈夫曼编码对txt文档实现压缩处理 | 算法分析之贪心算法设计 C语言版

    声明:凡代码问题,欢迎在评论区沟通.承蒙指正,一起成长! 目录 一.实验内容与要求 二.概要设计 三.直接上代码 四.运行结果 一.实验内容与要求 内容:哈夫曼编码是广泛地用于数据文件压缩的十分有效的 ...

  3. leetcode1414. 和为 K 的最少斐波那契数字数目(贪心算法)

    给你数字 k ,请你返回和为 k 的斐波那契数字的最少数目,其中,每个斐波那契数字都可以被使用多次. 斐波那契数字定义为: F1 = 1 F2 = 1 Fn = Fn-1 + Fn-2 , 其中 n ...

  4. 设计测试用例实现语句覆盖,判定覆盖,条件覆盖,判定/条件覆盖,条件组合覆盖,路径覆盖.

    第一题: 设计测试用例实现语句覆盖,判定覆盖,条件覆盖,判定/条件覆盖,条件组合覆盖,路径覆盖. [1]语句覆盖(设计若干个测试用例,使程序中的每个可执行语句至少执行一次) (x>3)& ...

  5. 算法分析与设计:贪心算法实现最少硬币找钱问题(支付+找零共花费硬币数最少)

    硬币找钱问题 Problem Description 设有六种不同面值的硬币,各硬币的面值分别为 5分,1角,2角,5角,1元,2元.现要用这些面值的硬币来购物和找钱.购物时可以使用的各面值的硬币个数 ...

  6. 三十六、贪心算法--集合覆盖问题

    一.贪心算法介绍 1.贪心算法(又称贪婪算法)是指,在对问题求解时,总是做出在当前看来是最好的选择.也就是说,不从整体最优上加以考虑,算法得到的是在某种意义上的局部最优解 2.贪心算法不是对所有问题都 ...

  7. 【算法笔记】:区间覆盖问题:贪心算法

    证明贪心算法的正确性: 下面证明: (1)最优子结构: 假设结果有n个区间,去掉最后一个区间及对应的点,则前n-1个区间仍然是覆盖所有点的所用的最少区间(最优解的子结构是子问题的最优解) 证明: cu ...

  8. c语言学生成员管理代码报告怎么写,C语言学生通信录管理系统课程设计报告

    <C语言学生通信录管理系统课程设计报告>由会员分享,可在线阅读,更多相关<C语言学生通信录管理系统课程设计报告(18页珍藏版)>请在人人文库网上搜索. 1.实验名称 :学生通信 ...

  9. 贪心算法【区间调度】【背包问题】【集合覆盖】【旅行商问题】【哈夫曼构造价值树】

    贪心算法  在对问题求解时,总是做出在当前看来是最好的选择.也就是说,不从整体最优上加以考虑,他所做出的是在某种意义上的局部最优解.  贪心算法不是对所有问题都能得到整体最优解,关键是贪心策略的选择, ...

最新文章

  1. ​超大规模时空数据的分布式存储与应用
  2. SpringMVC和Dubbo的整合
  3. 2021年北京高校数学建模校际联赛题目 出版社图书印制策略
  4. 基于不同STM32库函数的代码性能对比
  5. java class load 类加载
  6. 用hyperledger cello H3C分支创建单机模式区块链系统
  7. Android使用Sugar ORM创建数据库报no such table:...的解决方法
  8. HTML项目答辩演讲稿,办公楼毕业设计答辩演讲稿(答辩自述)
  9. 舞蹈模特欣欣(六)棚拍私房 大家看看像小龙女(李若彤)吗?
  10. Xmy的第二次python(文件操作)
  11. 极客日报:库克对话何同学:苹果很多功能来自中国消费者反馈;高通、微软、谷歌联合施压监管方:反对NVIDIA收购ARM...
  12. 水面渲染-浮力的一种实现
  13. 无人驾驶技术入门(五)| 没有视觉传感器,还谈什么无人驾驶?
  14. 支付宝 App 架构的原理与实战
  15. win7删除桌面计算机图标怎么删除,桌面无法删除的图标,详细教您win7桌面图标删不掉怎么办...
  16. 【转载】Amit’s A star Page 中译文
  17. 优效文件助手-【深度】都2021年了,你还只会用文件夹管理电脑文件?
  18. 14种方式,34个案例:对比SQL,学习Pandas操作
  19. 接口的多实现和多继承
  20. 微型计算机中主板上的主桥,什么是微型计算机一级维修与二级维修如何对主板进行二级维修...

热门文章

  1. html、aps网页设计,Dreamweaver8通过IIS建立站点对网页进行预览,设置详细方法
  2. 如何使用纯CSS3创建一个简单的五角星图形
  3. C# 打开文件夹FolderBrowserDialog与打开文件OpenFileDialog浅析
  4. 一个U盘加微信公众号实现互联网Wake On Wan(WOW/WOL)远程电脑开机
  5. Jscript之Ajax2 get请求和post请求
  6. (zt)CCB、CB1、CB2、OB
  7. 混沌图像---洛伦兹的蝴蝶
  8. 显卡交火支持linux系统吗,显卡交火性能提升多少_显卡交火怎么设置(步骤教程)...
  9. 大学开学的第一天——计算机达人成长之路(32)
  10. 10个Python图像处理工具,非常全了!