题意
给n个位于x轴上方的点,和一个半径r,问在x轴上最少多少个圆,可以将所有的点覆盖。
题解
首先,距x轴距离超过r的,显然是不可取的。
对于每个点,我们找一个恰能包含该点的,在x轴上最靠右的圆心,
这样当出现新的枚举右圆心时,
①若出现在该圆心左,
如r=5时,(-4,3)圆心在(0,0),(-3,5)圆心在(-3,0),
那么更新圆心在-3处即可,对于枚举右圆心,显然右边的圆心是不会出现在左圆心以左超过r的位置的。
这样,更新到(-3,0),就能包含两个圆。
②若出现在该圆心右,
则由于之前的圆是枚举的最右圆心,略右移即不能包含原来的点,
则只需判断该点与原圆心距离是否在r以内,
如在r以内则不需新建圆,否则需要另起一圆。
思路来源
https://blog.csdn.net/t__tsz/article/details/76557220
代码实现
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<cmath>
using namespace std;
int n,r;
double nowo;
struct node
{
int x,y;
};
node q[1005];
bool cmp(node a,node b)
{
if(a.x!=b.x)return a.x<b.x;
else return a.y>b.y;//同x轴情况下,距x轴更远,圆心越靠左
}
int main()
{
int cas=0;
while(~scanf("%d%d",&n,&r)&&n+r)
{
int maxy=0,ans=0;
for(int i=0;i<n;++i)
{
scanf("%d%d",&q[i].x,&q[i].y);
maxy=max(maxy,q[i].y);
}
printf("Case %d: ",++cas);
if(maxy>r)//有远离x轴超过半径的小岛
{
puts("-1");
continue;
}
sort(q,q+n,cmp);
nowo=q[0].x+sqrt(r*r-q[0].y*q[0].y*1.0);
ans++;
//初始圆心位置,向右建一个恰能包含该点的圆
for(int i=1;i<n;++i)
{
double tempo=q[i].x+sqrt(r*r-q[i].y*q[i].y*1.0);//同是向右建圆,故圆心不会出现在上个圆圆心左超过r的位置
if(tempo<nowo)nowo=tempo;
else if((nowo-q[i].x)*(nowo-q[i].x)+q[i].y*q[i].y>r*r)//由于这个圆是以某个点建的最右圆心圆,故无法右移圆心,只能判断距离是否小于r
{
ans++;
nowo=tempo;
}
}
printf("%d\n",ans);
}
return 0;
}