假设陆地的海岸线是一条无限延长的直线,海岛是一个个的点,现需要在海岸线上安装雷达,使整个雷达系统能够覆盖到所有的海岛。雷达所能覆盖的区域是以雷达为圆心半径为d的圆,我们用指标坐标系来描述,海岸线就是x轴,现在给出每个海岛的坐标与雷达的半径d,请编写一个程序计算出最少需要多少个雷达才能够将所有海岛全部覆盖?
输入:
输入将会有多组数据,每组数据第一行为n (1<=n<=1000),d,n为海岛个数,d为雷达半径,接下来n行,每行两个数描述海岛坐标。以n==0,d==0表示输入结束
输出:
每组数据对应一行,输出最少需要的雷达个数,如果不能满足,则输出-1,具体格式见样例。
样例输入:
3 2
1 2
-3 1
2 1
1 2
0 2
0 0
样例输出:
Case 1: 2
Case 2: 1
解题思路:该题题意是为了求出能够覆盖所有岛屿的最小雷达数目,每个小岛对应x轴上的一个区间,在这个区间内的任何一个点放置雷达,
则可以覆盖该小岛,区间范围的计算用[x-sqrt(d*d-y*y),x+sqrt(d*d-y*y)];这样,问题即转化为已知一定数量的区间,求最小数量的点,
使得每个区间内斗至少存在一个点。每次迭代对于第一个区间,选择最右边一个点, 因为它可以让较多区间得到满足, 如果不选择第一个区间
最右一个点(选择前面的点), 那么把它换成最右的点之后,以前得到满足的区间, 现在仍然得到满足,
所以第一个区间的最右一个点为贪婪选择, 选择该点之后, 将得到满足的区间删掉,进行下一步迭代, 直到结束。
#include<iostream>
#include<cmath>
#include<algorithm>
using namespace std;
struct p {
double x;
double y;
};
struct pp {
double head;
double end;
};
p point[1005];
pp points[1005];
bool c(pp x, pp y)
{
return x.head < y.head;
}
int main()
{
int n, d,j=0;
while (cin >> n >> d && (n != 0 || d != 0))
{
for (int i = 0; i < n; i++)
{
cin >> point[i].x >> point[i].y;
if (abs(point[i].y) > d)
{
cout << "Case " << ++j << ": -1" << endl;
continue;
}
points[i].head = point[i].x - sqrt(d*d - point[i].y*point[i].y);
points[i].end = point[i].x + sqrt(d*d - point[i].y*point[i].y);
}
sort(points, points + n, c);
double t = points[0].end;
int k = 1;
for (int i = 1; i < n; i++)
{
if (points[i].head > t)
{
k++;
t = points[i].end;
}
}
j++;
cout << "Case " << j << ": " << k << endl;
}
return 0;
}