【YBTOJ】【Luogu P1325】雷达安装
题目大意:
有 \(n\) 个点,第 \(i\) 个点的坐标是 \((x_i,y_i)\)。现在要你在 \(x\) 轴上标记若干个位置,使得每个点都能被一个以被标记位置为圆心,半径为 \(d\) 的圆覆盖。求最少标记多少位置。
正文:
首先任意一点如果的 \(y\) 坐标如果大于 \(d\),那么肯定覆盖不到,直接输出 -1
。
接下来考虑用贪心求解这个问题。
容易发现,点 \(i\) 要被覆盖,被覆盖的圆的圆心在 \(x\) 轴上,是一段区间,就是说此区间上的每一个点都能把点 \(i\) 覆盖。
既然如此,我们枚举点 \(i\) 的区间的右端点作为一个标记位置,当枚举到下一个点时,如果此标记位置在当前点区间内,则代表可以直接覆盖;如果不在,则用当前点的区间右端点作为新的标记位置。
代码:
const int N = 1010;
int n, m;
struct Interval
{
double l, r;
}a[N];
bool cmp (Interval a, Interval b)
{
return a.r < b.r;
}
int main()
{
scanf ("%d%d", &n, &m);
for (int x, y, i = 1; i <= n; i++)
{
scanf ("%d%d", &x, &y);
if(y > m) {puts("-1"); return 0;}
a[i].l = x * 1.0 - sqrt(m * m - y * y + 0.0);
a[i].r = x * 1.0 + sqrt(m * m - y * y + 0.0);
}
sort (a + 1, a + 1 + n, cmp);
double R = a[1].r;
int ans = 1;
for (int i = 2; i <= n; i++)
{
if (a[i].l <= R && R <= a[i].r) continue;
else
ans ++, R = a[i].r;
}
printf ("%d", ans);
return 0;
}