Description
将一条海岸线看成X轴,X轴上面是大海,海上有若干岛屿,给出雷达的覆盖半径和岛屿的位置,要求在海岸线上建雷达,在雷达能够覆盖全部岛屿情况下,求雷达的最少使用量
Input
多组用例,每组用例第一行为两个整数n,d(1<=n<=1000)分别表示岛屿数量和雷达范围,后面n行每行两个整数x,y表示该岛屿横,纵坐标,以n=0,d=0结束输入
Output
对于每组用例,如果雷达可以覆盖全部岛屿则输出雷达最少使用量,否则输出-1
Sample Input
3 2
1 2
-3 1
2 1
1 2
0 2
0 0
Sample Output
Case 1: 2
Case 2: 1
Solution
贪心
从左到右建立雷达,要尽量多地覆盖岛屿。以岛屿的圆心d为半径的圆与x轴有或者没有交点。如果存在没有交点的则不能实现。都存在交点的话,对于第i个岛屿计算出左右交点的x坐标保存在pos[i].l和pos[i].r里。对pos[i].l排序,然后一次从左到右找雷达。初始ll=pos[0].l为当前最左边的坐标,rr=pos[1].r为当前最右边的坐标,则对于下一个考虑岛屿i,如果pos[i].l>rr,则当前需要建立的雷达不能覆盖它,需要以此开始建立下一个雷达;否则,如果rr>pos[i].r,则需要更新rr=pos[i].r,如果ll>pos[i].l,则需要更新ll=pos[i].l,考虑下一个岛屿。别忘了最后需要建立雷达,即ans++:
Code
#include<cstdio>
#include<cmath>
#include<iostream>
#include<algorithm>
using namespace std;
#define maxn 1001
int n,d;
struct node
{
int x,y;//岛屿横,纵坐标
double l,r;//岛屿左,右交点
}pos[maxn];
bool operator<(node a,node b)
{
return a.l<b.l;
}
int main()
{
int res=1;
while(scanf("%d%d",&n,&d),n)
{
int flag=1;
for(int i=0;i<n;i++)
{
scanf("%d%d",&pos[i].x,&pos[i].y);
if(pos[i].y>d)
flag=0;
}
if(!flag||d<=0)//存在没有交点的岛屿,不能实现
{
printf("Case %d: -1\n",res++);
continue;
}
for(int i=0;i<n;i++)//计算第i个岛屿的左右交点
{
pos[i].l=pos[i].x-sqrt((double)(d*d-pos[i].y*pos[i].y));
pos[i].r=pos[i].x+sqrt((double)(d*d-pos[i].y*pos[i].y));
}
sort(pos,pos+n);//对左交点升序排序
int ans=0;
double ll,rr;
for(int i=0;i<n;ans++)//如果pos[i].l>rr,则当前需要建立的雷达不能覆盖它,需要以此开始建立下一个雷达
{
ll=pos[i].l;//当前最左边的坐标
rr=pos[i++].r;//当前最右边的坐标
while(i<n&&pos[i].l<=rr)//
{
ll=ll>pos[i].l?ll:pos[i].l;//更新rr
rr=rr<pos[i].r?rr:pos[i].r;//更新ll
i++;//考虑下一个岛屿
}
}
printf("Case %d: %d\n",res++,ans);
}
return 0;
}