R a d a r I n s t a l l a t i o n Radar\ Installation Radar Installation
题目链接:POJ 1328
题目大意
在平面直角坐标系上有
n
n
n个小岛,现在让你在
x
x
x轴上布置雷达,每个雷达可以侦测以它为原心,半径为
m
m
m的半环内的所有小岛(半环位于平面直角坐标系的一二象限),现在问侦测完这
n
n
n个小岛最少要多少个雷达?
(如果无论如何都侦测不完这
n
n
n个小岛,则答案为
−
1
-1
−1)
样例输入
3 2
1 2
-3 1
2 1
1 2
0 2
0 0
样例输出
Case 1: 2
Case 2: 1
思路
这道题用贪心来做。
我们可以通过小岛的坐标计算出
x
x
x轴上一端能检测它的区间。
那么,我们可以将问题转化为:给
N
N
N个区间,在
x
x
x轴上放置最小的点,使得每个区间包含至少一个点。
我们可以把所有区间按最右端点从小到大排序,然后枚举每个区间,如果其左端点大于前一个区间的右端点,就多加一个点(雷达),放在这个区间的最右端点。
最后,我们统计出点(雷达)的数量,就是最终的答案了。
(记得,如果小岛在第三第四象限或者
y
y
y坐标大于
m
m
m,则无法检测到,答案要变成
−
1
-1
−1)
代码
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<cmath>
using namespace std;
struct building
{
double min,max;
}a[1001];
int n,d,c,ans;
double x,y,right;
bool no;
bool cmp(building x,building y)
{
return x.max<y.max;
}
int main()
{
scanf("%d%d",&n,&d);//读入
while (n&&d)
{
if (n==0&&d==0) break;//判断是否结束
no=0;ans=1;//初始化
for (int i=1;i<=n;i++)
{
scanf("%lf%lf",&x,&y);//读入
if ((y>d||y<0)&&!no) no=1;//不能侦测到这个小岛
else if (!no)
{
double l=sqrt((double)(d*d)-y*y);
a[i].min=x-l;//求出最左端点
a[i].max=x+l;//求出最右端点
}
}
if (no)
{
printf("Case %d: -1\n",++c);//不能侦测到所有的小岛
scanf("%d%d",&n,&d);//读入
continue;
}
sort(a+1,a+n+1,cmp);//按最右端点从小到大排序
right=a[1].max;//记录最右端点
for (int i=1;i<=n;i++)
if (a[i].min>right)//下一个点的最左端点在最右端点右边(之前的端点不可以可以侦测到这个小岛)
{
right=a[i].max;//更新最右端点
ans++;//需要的雷达数加一
}
printf("Case %d: %d\n",++c,ans);//输出雷达数
scanf("%d%d",&n,&d);//读入
}
return 0;
}