112-雷达设备

题目描述

关系

905-区间选点

内容

假设海岸是一条无限长的直线,陆地位于海岸的一侧,海洋位于另外一侧。

每个小岛都位于海洋一侧的某个点上。

雷达装置均位于海岸线上,且雷达的监测范围为 d,当小岛与某雷达的距离不超过 d 时,该小岛可以被雷达覆盖。

我们使用笛卡尔坐标系,定义海岸线为 x 轴,海的一侧在 x 轴上方,陆地一侧在 x 轴下方。

现在给出每个小岛的具体坐标以及雷达的检测范围,请你求出能够使所有小岛都被雷达覆盖所需的最小雷达数目。

输入格式

第一行输入两个整数 nd,分别代表小岛数目和雷达检测范围。

接下来 n 行,每行输入两个整数,分别代表小岛的 xy 轴坐标。

同一行数据之间用空格隔开。

输出格式

输出一个整数,代表所需的最小雷达数目,若没有解决方案则所需数目输出 1

数据范围

1n1000,
1000x,y1000

输入样例:

3 2
1 2
-3 1
2 1

输出样例:

2

问题分析

最初思路

每个小岛离海岸线最近的距离是垂直线。假设所有小岛离 x 轴的距离不超过 d,那么最多需要 n 个雷达站就可以直接覆盖了。这几个雷达站只需要设置在每个小到的垂直线处即可。

然后,我们尝试一个个的缩小雷达站的数量。对于每个雷达站判断,一个雷达站能够囊括多少小岛。

具体的逻辑可以表示为:

for (雷达站i)
	for (小岛j)
		if (小岛距离雷达站的距离 <= d)
			删除这座小岛对应的垂直雷达站
			记录这座小岛的下标x
			j = x

思路分析

逆向思维,对于每个小岛来说,雷达建在哪里才可以覆盖到小岛。
image.png

可以发现,我们只要将雷达站建在圈内,就可以覆盖到小岛了,所以问题就转化为了如何选择最少的点数,使得可以覆盖全部的区间,这就是 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;
}