题目链接:
http://acm.nyist.edu.cn/JudgeOnline/problem.php?pid=12
题目大意:
有一块草坪,横向长w,纵向长为h,在它的橫向中心线上不同位置处装有n(n<=10000)个点状的喷水装置,每个喷水装置i喷水的效果是让以它为中心半径为Ri的圆都被润湿。请在给出的喷水装置中选择尽量少的喷水装置,把整个草坪全部润湿。
传送门:喷水装置(一)
思路:
区间覆盖问题,每个点有一段喷水区间,按照左端点排序即可,设置两变量begin, end,依次扫过去,每次取覆盖begin的区间更新end,如果没能覆盖begin,说明已经到了当前的最右端,begin=end,再次扫描,如果每次扫描开始的时候就不能覆盖begin,则无解,如果每次扫描的时候没有找到合适的end,也无解。如果最终的begin<l也表示到达不了终点。
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<cmath> 6 using namespace std; 7 const int maxn = 1e4 + 10; 8 int T, n;double l, w; 9 struct node 10 { 11 double x, y; 12 bool operator < (const node a)const 13 { 14 return x < a.x; 15 } 16 node(){} 17 node(double x, double y):x(x), y(y){} 18 }; 19 node a[maxn]; 20 int main() 21 { 22 cin >> T; 23 while(T--) 24 { 25 cin >> n >> l >> w; 26 w = w * 0.5; 27 int tot = 0; 28 double x, r; 29 for(int i = 0; i < n; i++) 30 { 31 cin >> x >> r; 32 if(r <= w)continue; 33 double c = sqrt(1.0 * r * r - w * w); 34 a[tot].x = 1.0 * x - c; 35 a[tot++].y = 1.0 * x + c; 36 if(a[tot - 1].x > l || a[tot - 1].y < 0)tot--; 37 } 38 sort(a, a + tot); 39 double begin = 0, end = -1; 40 int ans = 0; 41 for(int i = 0; i < tot && begin < l;) 42 { 43 if(a[i].x > begin) 44 { 45 ans = 0; 46 break; 47 } 48 while(i < tot && a[i].x <= begin)//覆盖begin的区间更新出最大的end 49 { 50 end = max(end, a[i].y); 51 i++; 52 } 53 if(end < 0)//说明没有找到合适的区间,直接无解 54 { 55 ans = 0; 56 break; 57 } 58 ans++; 59 begin = end;//更新两者 60 end = -1; 61 } 62 if(begin < l)ans = 0; 63 cout<<ans<<endl; 64 } 65 return 0; 66 }