112-雷达设备
题目描述
关系
内容
假设海岸是一条无限长的直线,陆地位于海岸的一侧,海洋位于另外一侧。
每个小岛都位于海洋一侧的某个点上。
雷达装置均位于海岸线上,且雷达的监测范围为
我们使用笛卡尔坐标系,定义海岸线为
现在给出每个小岛的具体坐标以及雷达的检测范围,请你求出能够使所有小岛都被雷达覆盖所需的最小雷达数目。
输入格式
第一行输入两个整数
接下来
同一行数据之间用空格隔开。
输出格式
输出一个整数,代表所需的最小雷达数目,若没有解决方案则所需数目输出
数据范围
输入样例:
3 2
1 2
-3 1
2 1
输出样例:
2
问题分析
最初思路
每个小岛离海岸线最近的距离是垂直线。假设所有小岛离 x 轴的距离不超过 d,那么最多需要 n 个雷达站就可以直接覆盖了。这几个雷达站只需要设置在每个小到的垂直线处即可。
然后,我们尝试一个个的缩小雷达站的数量。对于每个雷达站判断,一个雷达站能够囊括多少小岛。
具体的逻辑可以表示为:
for (雷达站i)
for (小岛j)
if (小岛距离雷达站的距离 <= d)
删除这座小岛对应的垂直雷达站
记录这座小岛的下标x
j = x
思路分析
逆向思维,对于每个小岛来说,雷达建在哪里才可以覆盖到小岛。

可以发现,我们只要将雷达站建在圈内,就可以覆盖到小岛了,所以问题就转化为了如何选择最少的点数,使得可以覆盖全部的区间,这就是 905-区间选点问题了。
执行流程设计
总结
代码实现
#include <bits/stdc++.h>
using namespace std;
const int N = 1010;
const double eps = 1e-6, INF = 1e20;
int n, d;
struct re {
double x, y;
bool operator<(const re &r) const{
return y < r.y;
}
} re[N];
int main()
{
cin >> n >> d;
for (int i = 0; i < n; i++) {
int x, y;
cin >> x >> y;
if (y > d) {
cout << -1;
return 0;
}
double l, r;
l = x - sqrt(d * d - y * y), r = x + sqrt(d * d - y * y);
re[i] = {l, r};
}
sort(re, re + n);
// 区间选点问题
double last = -INF; // 上一个点的位置
int cnt = 0;
for (int i = 0; i < n; i++) {
if (last < re[i].x) {
last = re[i].y;
cnt++;
}
}
cout << cnt;
return 0;
}