假设有一条无限长的海岸线,海岸线以上部分有n个岛屿。在海岸线上有雷达,每个雷达能够探测的范围为半径为d的圆,当且仅当一个岛屿与雷达的距离小于等于d时,岛屿能被雷达探测到。给出所有岛屿的坐标和雷达的半径。求最少需要用多少个雷达,使得所有的岛屿都被探测到。
使用贪心+快排,求出每个岛屿对应圆心在x轴上的范围,对左坐标排序后贪心选择。类似于:数轴上有N个点,要用几个单位长度区间才能将它们全部覆盖?具体实现见代码注释。
使用贪心+快排,求出每个岛屿对应圆心在x轴上的范围,对左坐标排序后贪心选择。类似于:数轴上有N个点,要用几个单位长度区间才能将它们全部覆盖?具体实现见代码注释。
这次用到了C语言的库函数qsort,写cmp函数的时候要注意浮点数的比较。另外这个排序只需要考虑左坐标即可,因为就算左坐标相同也不会影响结果,贪心算法会自动更正右坐标的选择。
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
typedef struct
{
double left;
double right;
}point;
point p[1001];
int n, d, sum;
/* 按左坐标排序 */
int cmp(const void *a, const void *b)
{
return (*(point*)a).left >= (*(point*)b).left ? 1 : -1;
}
void Solve()
{
int i;
double std;
/* 对岛坐标进行排序 */
qsort(p, n, sizeof(point), cmp);
sum = 1;
/* 标准值为第一个点右坐标 */
std = p[0].right;
/* 从最左边开始扫描 */
for (i = 1; i < n; i++)
{
/* 某点左坐标比标准值大则雷达 + 1,更新标准值为该点右坐标 */
if (p[i].left > std)
{
std = p[i].right;
sum++;
}
else
{
/* 某点右坐标比标准值小,更新标准值为该点右坐标 */
if (p[i].right < std)
{
std = p[i].right;
}
}
}
}
int main()
{
int x, y, i, t, fail;
double l;
t = 1;
while(1)
{
fail = 0;
scanf("%d%d", &n, &d);
if(n + d == 0) break;
for (i = 0; i < n; i++)
{
scanf("%d%d", &x, &y);
/* 若岛超出雷达范围则标记失败 */
if (y > d)
{
fail = 1;
}
else
{
/* 求出雷达范围X轴方向上岛的临域 */
l = sqrt((double)(d * d - y * y));
/* 岛可安雷达的最左坐标 */
p[i].left = x - l;
/* 岛可安雷达的最右坐标 */
p[i].right = x + l;
}
}
if (fail)
{
sum = -1;
printf("Case %d: %d\n", t++, sum);
}
else
{
Solve();
printf("Case %d: %d\n", t++, sum);
}
}
//system("pause");
return 0;
}