实验任务
小菇凉和小光头来到了一片黑漆漆的水域,他们必须穿过水域拿到大龙 buff 才可能打败大魔王。可是聪明的大魔王在水域上设置了许多的隐形假眼来监视是否有人偷 buff,只有真眼监视才能看到假眼。小光头想了个办法,在岸边设置一些真眼来时时观测假眼的分布,真眼只能设置在岸边(X 轴),且只能监视以真眼为中心半径为 d 的圆形区域的假眼。可是真眼很贵,小菇凉和小光头希望用最少的真眼来检测所有的假眼。
数据输入
输入包括多组数据,每组数据第一行包括,n 和 d 表示假眼的个数和真眼监视范围。(输入 0 0 时结束)
接下来 n 行每行两个整数 x、Y 表示假眼的坐标。
数据输出
输出最少需要多少雷达才能监视所有的监视塔。
如果不能,则输出-1。
输入示例
3 2
1 2
-3 1
2 1
1 2
0 2
0 0
输出示例
2
1
解题思路
把点转换成区间相交问题。
假设我们现在正在进行操作的区间是[l,r],然后,当我们来到一个新的区间[l1,r1]时,有以下三种情况:
(1) l < r < l1 < r1 说明新区间已经跟我们之前的区间没有关系了,直接把答案+1,更新l和r
(2) l < l1 < r < r1 这种情况下,实质区间是(l1,r) 因为我们关心的区间的右端点,所以不做操作
(3) l < l1 < r1 < r 实质区间为(l1,r1) ,更新l和r即可
参考代码
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <iostream>
using namespace std;
const int maxn = 10010;
struct Node{
double x,y;
double l,r;
}p[maxn];
bool cmp(const Node& p1,const Node& p2){
return ((p1.l < p2.l) || (p1.l == p2.l && p1.r < p2.r));
}
int n,i,j;
double d,pos,l,r;
int main()
{
while (~scanf("%d %lf",&n,&d) && (d || n)){
bool flag = true;
for (i = 1;i <= n;i++){
scanf("%lf%lf",&p[i].x,&p[i].y);
if (fabs(p[i].y) > d){ //无解情况判定
printf("-1\n");
flag = true;
break;
}
p[i].y = sqrt(d*d-p[i].y*p[i].y); //区间半径
p[i].l = p[i].x - p[i].y; //区间左端点
p[i].r = p[i].x + p[i].y; //区间右端点
}
if (flag){
sort(p+1,p+n+1,cmp);
int ans = 1;
l = p[1].l,r = p[1].r;
for (i = 2;i <= n;i++){
if (p[i].l > r){ //两个区间不相交,ans++
ans ++;
l = p[i].l;
r = p[i].r;
}
if (p[i].l > l && p[i].l < r)
l = p[i].l;
if (p[i].r < r)
r = p[i].r;
}
printf("%d\n",ans);
}
}
return 0;
}