1. 程式人生 > >poj1328 Radar Installation (貪心)

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以內則不需新建圓,否則需要另起一圓。

思路來源

程式碼實現

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