给定平面上n (n≤105) 个点和一个值D,要求在x轴上选出尽量少的点,使得对于给定的每个点,都有一个选出的点离它的欧几里德距离不超过D。(本段摘自《算法竞赛入门经典(第2版)》)
分析:
以给定点为圆心,D为半径画圆,与x轴交与l和r,则问题就转化成了给定x轴上的一些线段,要求用最少的点使得每个线段中至少包含一个点。可以用贪心的想法,把线段按照结束的点排序,扫描一遍就好了。
#include <iostream>
#include <fstream>
#include <cstdio>
#include <cstring>
#include <vector>
#include <queue>
#include <map>
#include <string>
#include <cmath>
#include <algorithm>
#include <sstream>
using namespace std;
const int maxn = 100005;
struct node
{
double l, r;
int idx;
bool operator < (const node& right) const
{
return fabs(r - right.r) < 1e-8 ? (l > right.l) : (r < right.r);
}
};
int l, n, ans;
double x, y, dx, d, pos;
node a[maxn];
int main()
{
while (~scanf("%d%lf%d", &l, &d, &n))
{
for (int i = 0; i < n; ++i)
{
scanf("%lf%lf", &x, &y);
dx = sqrt(d * d - y * y);
a[i].l = x - dx;
a[i].r = x + dx;
a[i].idx = i;
}
sort(a, a + n);
ans = 1;
pos = a[0].r;
for (int i = 1; i < n; ++i)
if (a[i].l - 1e-8 < pos)
continue;
else
{
pos = a[i].r;
++ans;
}
printf("%d\n", ans);
}
return 0;
}