poj1328 Radar Installation (贪心)

题意

给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;
}

猜你喜欢

转载自blog.csdn.net/Code92007/article/details/82913600