假设海岸是一条无限长的直线,陆地位于海岸的一侧,海洋位于另外一侧。
每个小岛都位于海洋一侧的某个点上。
雷达装置均位于海岸线上,且雷达的监测范围为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个区间,问题转换成了寻找最少的点覆盖所有区间。
那么我们维护的是最大连续相交的区间
这个可以按右端点排序,然后每次检验当前端点左端点是否小于上一个雷达,否则增加一个雷达在这个左端点上。
再或者可以按左端点排序,不同的是雷达放置在最小的右端点上,每次也判断当前点的左端点是否小于雷达坐标。这和右端点排序实质是一样的,因为只要出现了不相交的线段就要多一个雷达,而放置在最小的右端点上才能保证第一次出现了不相交线段前的线段都被雷达覆盖了。
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
struct Node
{
double x,y;
}nodes[1005];
int cmp(Node a,Node b)
{
return a.x < b.x;
}
int main()
{
int n,d;scanf("%d%d",&n,&d);
int flag = 0;
for(int i = 1;i <= n;i++)
{
int x,y;
scanf("%d%d",&x,&y);
if(y > d)flag = 1;
double num = sqrt(d * d - y * y);
nodes[i].x = (double)x - num;
nodes[i].y = (double)x + num;
}
if(flag)
{
printf("-1\n");
return 0;
}
sort(nodes + 1,nodes + 1 + n,cmp);
double pre = -1e9;
int ans = 0;
for(int i = 1;i <= n;i++)
{
if((double)nodes[i].x - pre > 1e-6)
{
ans++;
pre = nodes[i].y;
}
else pre = min(nodes[i].y,pre);
}
printf("%d\n",ans);
return 0;
}