蓝桥杯--贪心2 AcWing 112. 雷达设备
作者:互联网
AcWing 112. 雷达设备
假设海岸是一条无限长的直线,陆地位于海岸的一侧,海洋位于另外一侧。
每个小岛都位于海洋一侧的某个点上。
雷达装置均位于海岸线上,且雷达的监测范围为 d,当小岛与某雷达的距离不超过 d 时,该小岛可以被雷达覆盖。
我们使用笛卡尔坐标系,定义海岸线为 x 轴,海的一侧在 x 轴上方,陆地一侧在 x 轴下方。
现在给出每个小岛的具体坐标以及雷达的检测范围,请你求出能够使所有小岛都被雷达覆盖所需的最小雷达数目。
输入格式
第一行输入两个整数 n 和 d,分别代表小岛数目和雷达检测范围。
接下来 n 行,每行输入两个整数,分别代表小岛的 x,y 轴坐标。
同一行数据之间用空格隔开。
输出格式
输出一个整数,代表所需的最小雷达数目,若没有解决方案则所需数目输出 −1。
数据范围
1≤n≤1000
输入样例:
3 2
1 2
-3 1
2 1
输出样例:
2
题意:x轴上方存在n个小岛,每个雷达有一个检测范围,求出在x轴上设立的最小雷达数量,使所有小岛能被监测到
典型贪心问题,例如给最左方的小岛一个雷达,如果想让这个雷达监测到更多的小岛,那么应该在不失去该小岛的情况下,尽可能的将雷达右移,一直到监测不到下一小岛再新建一枚
如果使用二维面积来计算的话很麻烦且很容易算错,由于雷达只会建立在x轴上,可以将一个小岛抽象成一个线段,线段的左端点代表雷达至少要到达这个位置才能监测到该小岛,同理超过右端点将检测不到,线段通过小岛坐标及雷达监测范围计算得出
获得n个小岛线段后,因为要尽可能的将雷达右移,因此将线段根据右端点排序,将第一个小岛的右端点设为雷达初始位置,如果该位置也被下一线段包含,则说明下一个小岛也可以被该雷达监测到,继续判断下一小岛直至不能被包含,则另起一雷达,将右端点设为雷达位置,重复判断至结束
代码如下
import java.io.*;
import java.util.*;
public class Main {
static Scanner tab = new Scanner(System.in);
static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
static BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
static int N = 1010;
//定义小岛线段类
static class pair implements Comparable<pair>{
double l;
double r;
public pair(double l, double r) {
super();
this.l = l;
this.r = r;
}
@Override
public int compareTo(pair o) {//根据右端点排序
// TODO Auto-generated method stub
return Double.compare(r, o.r);
}
}
public static void main(String[] args) throws IOException {
int n=tab.nextInt();
int d=tab.nextInt();
pair a[]=new pair[N];
boolean flag=true;//判断是否有解
for(int i=0;i<n;i++) {
int x=tab.nextInt();
int y=tab.nextInt();
if(y>d) {
flag=false;
}
else {
double len=Math.sqrt(d*d-y*y);//计算长度
a[i]=new pair(x-len,x+len);
}
}
if(!flag) {
System.out.println("-1");
return ;
}
Arrays.sort(a,0,n);
int res=1;//雷达数量
double k=a[0].r;//当前雷达位置
for(int i=1;i<n;i++) {
if(k>=a[i].l) {
continue;
}
k=a[i].r;//更新雷达
res++;
}
System.out.println(res);
}
}
标签:--,double,new,蓝桥,int,static,小岛,112,雷达 来源: https://blog.csdn.net/ooold_six/article/details/115529121