链接:
https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=4490
题意:
给定平面上n(n≤1e5)个点和一个值D,要求在x轴上选出尽量少的点,使得对于给定的每个点,
都至少有一个选出的点离它的欧几里德距离不超过D(每个给定的点离x轴的距离至多为D)。
分析:
区间覆盖问题。每个给定的点在x轴上都有一个选点区间,先令所有给定的点按x坐标升序排列,
则第1,2,3,...,x(1≤x≤n)个给定的点的选点区间的公共部分即为第一个选出的点的范围,以此类推。
代码:
1 #include <cstdio> 2 #include <cmath> 3 #include <algorithm> 4 using namespace std; 5 6 struct COORDINATE { 7 int x, y; 8 bool operator < (const COORDINATE& that) const { 9 return x < that.x; 10 } 11 } a[1000000]; 12 13 bool legal(double L, double R, double L2, double R2){ //判断[L2,R2]是否与[L,R]有公共部分 14 L = max(L, L2); R = min(R, R2); 15 return L <= R; 16 } 17 18 int main(){ 19 int len, d, n; 20 while(~scanf("%d%d%d", &len, &d, &n)){ 21 for(int i = 0; i < n; i++) scanf("%d%d", &a[i].x, &a[i].y); 22 sort(a, a + n); 23 24 int ans = 1; 25 double L = 0, R = len; 26 for(int i = 0; i < n; i++){ 27 double m = sqrt(d * d - a[i].y * a[i].y); 28 double L2 = a[i].x - m, R2 = a[i].x + m; //求出当前点的选点区间[L2,R2] 29 if(legal(L, R, L2, R2)) L = max(L, L2), R = min(R, R2); //更新公共部分 30 else L = max(0.0, L2), R = min((double)len, R2), ans++; 31 } 32 printf("%d\n", ans); 33 } 34 return 0; 35 }