正解思路:
相对原点而言,我们假定x负半周方向为“左”,x正半轴方向为“右”。
我们找一个岛屿能被侦测到的极限范围,在雷达侦测区(圆)的左半圆上或者在雷达侦测区(圆)的右半圆上,换句话说当岛屿到雷达的距离等于d时,
雷达可以位于岛屿的左侧也可以位于雷达的右侧。而这就可以分别确定雷达相对与岛屿x的最左坐标和x最右坐标。
最左为:x - sqrt(d*d-y*y); 最右为:x + sqrt(d*d-y*y);
每个岛屿都有这样的最左和最右可被侦测坐标。
根据贪婪的思想,每次都应该将最右可被侦测坐标作为衡量标准。
假定当前的岛屿为cur,当前的下一个为next。
1.如果next的最左可被侦测坐标比cur的最右都大的话,只能再设一个雷达来侦测next了。
2.如果next的最左可被侦测坐标比cur的最右小,这时会有两种情况。
A.next最右 < cur最右
B.next最右 >= cur最右
对于B情况,我们可以直接侦测到next了, 可以找next的next了.
对于A情况,也就等价于next包含于cur, 这样就应该把next的右最为衡量标准了.
因为这样可以左移最右坐标, 可以让可能更多的岛屿被侦测到(他们的最左与衡量标准有更多的交集)
具体实现看代码
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
typedef struct
{
double d1;
double d2;
}coordinate;
coordinate island[1001]={0};
int cmp(const void*a,const void *b)
{
if((*(coordinate *)a).d1>(*(coordinate *)b).d1)
return 1;
else
return -1;
}
int greedy(coordinate island[],int n,int d)
{
int i,num=1;
double cur;
cur=island[0].d2;
for(i=1;i<n;i++)
{
if(island[i].d1-cur>1e-5)
{
num++;
cur=island[i].d2;
}
else
{
if(island[i].d2-cur<1e-5)
cur=island[i].d2;
}
}
return num;
}
int main()
{
int n,d,x,y,flag=0,i,count=0;
double offset;
while(scanf("%d %d",&n,&d)==2&&(n!=0&&d!=0))
{
count++;
flag=0;
for(i=0;i<n;i++)
{
scanf("%d %d",&x,&y);
if(y>d) flag=1;
offset=sqrt(double(d*d-y*y));
island[i].d1=x-offset;
island[i].d2=x+offset;
}
if(flag>0)
{
printf("Case %d: -1\n",count);
continue;
}
qsort(island,n,sizeof(island[0]),cmp);
// for(i=0;i<n;i++)
// printf("%f %f\n",island[i].d1,island[i].d2);
i=greedy(island,n,d);
printf("Case %d: %d\n",count,i);
}
return 0;
}