题目大意
在x轴上方分布n(1<=n<=1000)个点,给出了这n个点的坐标。在x轴上的一个雷达能覆盖半径为d的区域,问最少需要多少雷达才能覆盖所有点。分析
最开始是想对雷达位置进行贪心(恰好能覆盖最左边的点的位置放雷达),但仔细想了之后发现这样不可行。
转换思路后,考虑对每个点都对应x轴上的一个区间,只有这个区间的雷达才能覆盖这个点。那么现在问题就变成了给定n个区间,选出k个点使得每个区间上至少有一个点的k的最小值。这样问题就变成了一个比较典型的贪心问题了:按照区间的右端点作为关键字升序排序,从左到右开始扫描,用一个变量cur来表示当前扫描到的位置,对于当前区间的左端点如果小于等于cur那么看下一个区间;若大于,ans++,并更新cur的值为这个区间的右端点,看下一个区间.注意
应该注意d<y以及d为负的特殊情况代码
#include<cstdio>
#include<iostream>
#include<cmath>
#include<cstring>
#include<cstdlib>
#include<queue>
using namespace std;
const double INF=999999999;
int n;
double d;
struct LINE
{
double s;
double t;
}line[1005];
int num=0;
int Cmp(const void *p1,const void *p2)
{
return ((LINE *)p2)->t < ((LINE *)p1)->t ? 1 : -1;
}
int main()
{
int Case=0;
double x,y;
int flag=0;
while(scanf("%d%lf",&n,&d))
{
flag=0;
if(d<0)flag=1;
num=0;
if(n==0 && d==0)break;
for(int i=1;i<=n;i++)
{
scanf("%lf%lf",&x,&y);
if(y>d)flag=1;
line[++num].s=x-sqrt(d*d-y*y);
line[num].t=x+sqrt(d*d-y*y);
}
if(flag==1)
{
printf("Case %d: -1\n",++Case);
continue;
}
qsort(line+1,num,sizeof(line[0]),Cmp);
double cur=line[1].t;
int ans=1;
for(int i=2;i<=num;i++)
{
if(line[i].s<=cur)continue;
else
{
ans++;
cur=line[i].t;
}
}
printf("Case %d: %d\n",++Case,ans);
}
return 0;
}