题面
假设海岸是一条无限长的直线,陆地位于海岸的一侧,海洋位于另外一侧。
每个小岛都位于海洋一侧的某个点上。
雷达装置均位于海岸线上,且雷达的监测范围为d,当小岛与某雷达的距离不超过d时,该小岛可以被雷达覆盖。
我们使用笛卡尔坐标系,定义海岸线为x轴,海的一侧在x轴上方,陆地一侧在x轴下方。
现在给出每个小岛的具体坐标以及雷达的检测范围,请你求出能够使所有小岛都被雷达覆盖所需的最小雷达数目。
输入格式
第一行输入两个整数n和d,分别代表小岛数目和雷达检测范围。
接下来n行,每行输入两个整数,分别代表小岛的x,y轴坐标。
同一行数据之间用空格隔开。
输出格式
输出一个整数,代表所需的最小雷达数目,若没有解决方案则所需数目输出“-1”。
数据范围
1≤n≤1000
输入样例:
3 2
1 2
-3 1
2 1
输出样例:
2
思路
题意就不解释了。那么我们刚开始的想法肯定是取考虑怎么在区间里面取雷达可以最优,但是呢,你会发现这样做并不能找到一个最优的策略,这时候我们需要换一个角度看问题。我们考虑一个点可以被哪些雷达覆盖,你会发现,这些雷达点会构成一个区间,而我们要做的就是区间的选择,我们要在安排一些点使得每一个区间都有一个点,那么这个问题就转换成了一个区间贪心问题。我们按照右端点排序,每次取右端点作为这个区间的点,这样可以做到贪心的目的,他可以尽可能的满足后面的点。所以我们在写贪心的题目的时候不能思维定式,我们要从不同角度看待问题,使得问题最终转化成为我们熟悉的贪心模型。
代码实现
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<iostream>
#include<queue>
#include<cstring>
using namespace std;
typedef long long ll;
const int maxn=1010;
const double eps=1e-6,inf=1e10;
typedef pair <double,double > PII;
int n,d;
PII a[maxn];
int main () {
cin>>n>>d;
bool flag=1;
for (int i=1,x,y;i<=n;i++) {
cin>>x>>y;
if (y>d) {
flag=0;
break;
}
double len=sqrt (d*d-y*y);
a[i]={x+len,x-len};
}
if (!flag) cout<<-1<<endl;
else {
sort (a+1,a+1+n);
int ans=0;
double last=-inf;
for (int i=1;i<=n;i++) {
if (a[i].second>last+eps) {
ans++;
last=a[i].first;
}
}
cout<<ans<<endl;
}
return 0;
}