题目大意:
给定x轴上方n个点的坐标和一个半径,求出x轴上的最少点的个数,使得以这些点为圆心的圆覆盖住x轴上方所有的点
解法:
首先,如果存在y>d的点,那就没有solution
由点的纵坐标和半径可以确定出覆盖住每个点的圆心的横坐标范围
将这些范围按起点优先排序,
为了尽可能的少用x轴上的点,就要使得每个点尽可能的向右
即对于范围的左端点在最左端的点,要取其右端点作为圆心位置
若紧邻的后面的范围的左端点在这个圆心的右侧,那么total++;
若后面的区间被这个区间所覆盖,那么选择后面区间的右端点(因为小区间里取了一个满足条件的点,大区间里一定可以取到)
代码:
#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<string.h>
#include<cmath>
#include<algorithm>
using namespace std;
const int maxisland = 1010;
const double eps = 1e-20;
class island{
public:
double start,end;
}Island[maxisland];
int n,d;
bool cmpIsland(const island & item1,const island &item2){ //按间隔降序排列
double dif = fabs(item1.start - item2.start);
if(dif < eps){
return item1.end < item2.end;
}
return item1.start < item2.start;
}
int main(){
//freopen("2.txt","w",stdout);
int i,j,Case = 0,xx,yy,total;
bool toofar;
double dis,start,end,dis1,dis2;
while(scanf("%d%d",&n,&d)!=EOF){
if(n == 0 && d == 0)
break;
memset(Island,0,sizeof(Island));
toofar = false;
for(i = 0; i < n; ++i){
scanf("%d%d",&xx,&yy);
if(yy > d){ //如果y方向的距离大于雷达的半径,说明不能完成
toofar = true;
for(j = i + 1; j < n; ++j){ //读入这一组里剩余的数据
scanf("%d%d",&xx,&yy);
}
break;
}
dis = (double)sqrt((double)(d*d-yy * yy));
start = (double)xx - dis;
end = (double)xx + dis;
Island[i].start = start; Island[i].end = end;
}
if(toofar){
printf("Case %d: -1\n",++Case);
continue;
}
sort(Island,Island+n,cmpIsland);
double left,right;
left = Island[0].start; right = Island[0].end;
total = 1;
int cnt = 1;
while(cnt < n){
if(Island[cnt].start > right){
left = Island[cnt].start;
right = Island[cnt].end;
++total;
}
else if(Island[cnt].end < right){
right = Island[cnt].end;
}
++cnt;
}
printf("Case %d: %d\n",++Case,total);
}
return 0;
}