假设海岸线是一条无限延伸的直线,陆地在海岸线的一侧,海洋在另外一侧。每个小岛相当于海洋侧的一个点。坐落在海岸线上的基站只能覆盖半径为d的范围。应用直角坐标系,将海岸线作为x轴,设海洋侧在x轴上方。给定海洋中各小岛的位置,以及通信基站的覆盖半径,要求用最少的基站覆盖所有小岛,使得每个小岛都能和陆地通过某基站通信(在某个基站覆盖范围内)。
输入:小岛数目,基站覆盖半径,各小岛坐标;
输出:覆盖小岛的最少基站数目及基站坐标,如果无解,输出-1.;
代码:
package stest;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
import java.util.Scanner;
import stest.Test3.Island;
public class Test3 {
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
System.out.print("输入小岛的个数:");
int n = scan.nextInt();
System.out.print("输入雷达半径:");
int d = scan.nextInt();
//初始化小岛集合
List<Island> islands = new ArrayList<>(n);
//将小岛都添加到集合中
for(int i = 1; i <= n; i++) {
System.out.print("输入第" + i +"个小岛的坐标:");
int x = scan.nextInt();
int y = scan.nextInt();
Island island = new Island(x, y, d);
islands.add(island);
}
//将小岛排序
Collections.sort(islands,new Comparator<Island>() {
@Override
public int compare(Island o1, Island o2) {
return (int) (o1.px -o2.px);
}
});
//保存小岛集合的副本便于最后的合理性检验
List<Island> copyIslands = new ArrayList<>(n);
copyIslands.addAll(islands);
//第一个基站坐标
double yuanxin = islands.get(0).circleCenterx;
boolean flag = false;
//判断是否无解
int A = 1;
//第一个小岛无需检测
int B = 1;
for (Iterator<Island> iterator = islands.iterator(); iterator.hasNext();) {
Island nisland = (Island) iterator.next();
if (nisland.y > d) {
A = -1;
break;
}
if (B == 1) {
B = 0;
continue;
}
flag = Math.pow(yuanxin - nisland.x, 2) + Math.pow(nisland.y, 2) <= Math.pow(d, 2);
if (flag) {
//如果基站能包括这个岛,就将这个岛从集合中删掉
iterator.remove();
}else {
//否则将这个岛对应的圆心作为新的基站坐标
yuanxin = nisland.circleCenterx;
}
}
if (A == -1) {
System.out.println(-1);
}else {
System.out.println(islands.size());
for (Iterator iterator = islands.iterator(); iterator.hasNext();) {
Island island = (Island) iterator.next();
System.out.println(island.circleCenterx + " 0");
}
}
//合理性检验
scan.close();
}
/**
* @author ZHS
* param circleCenterx 以d为半径的且该小岛在圆周上的圆的圆心,即基站坐标
* param px 圆与X轴的交点的左端点
*
*/
static class Island {
double px;
double circleCenterx;
int x;
int y;
public Island(int x, int y, int d) {
this.x = x;
this.y = y;
circleCenterx = x + Math.sqrt(Math.pow(d, 2) - Math.pow(y, 2));
px = circleCenterx - d;
}
@Override
public String toString() {
return "Island [px=" + px + ", circleCenterx=" + circleCenterx + ", x=" + x + ", y=" + y + "]";
}
}
}
结果截图: