AcWing_112 雷达设备(贪心)

AcWing

112. 雷达设备

(贪心) $O(nlogn)$

如下图所示,对于任意一个小岛$(x,y)$,我们都可以在海岸线上求出能覆盖该小岛的建造雷达的区间$[a,b]$.

image

由勾股定理可知:

$a=x-\sqrt{d^2-y^2}$,

$b=x+\sqrt{d^2-y^2}$.

将所有小岛转化成区间后,问题转化为:给定$n$个区间,在$x$轴上选择尽量少的点,使得所有区间至少包含一个点。

算法步骤:

  • 将所有区间按右端点从小到大排序;
  • 依次考虑每个区间:
    • 如果当前区间包含最后一个选择的点,则直接跳过;
    • 如果当前区间不包含最后一个选择的点,则在当前区间的右端点的位置选一个新的点。
#include <bits/stdc++.h>
using namespace std;
int n, d;
const int N = 1010;
typedef pair<double, double> PDD;
#define xx first
#define yy second
PDD seg[N];
const double eps = 1e-6;
bool cmp(PDD u, PDD v){ return u.yy < v.yy; }
int main(){
    ios::sync_with_stdio(0);
    cin.tie(0); cout.tie(0);
    cin >> n >> d;
    for(int i = 0; i <= n - 1; i ++){
        int x, y;
        cin >> x >> y;
        if(y > d){
            cout << -1;
            return 0;
        }
        seg[i].xx = x - sqrt(d * d - y * y);
        seg[i].yy = x + sqrt(d * d - y * y);
    }
    sort(seg, seg + n, cmp);
    int res = 0;
    double rr = seg[0].xx - 1;
    for(int i = 0; i <= n - 1; i ++){
        if(seg[i].xx <= rr) continue;
        rr = seg[i].yy;
        res ++;
    }
    cout << res;
    return 0;
}