nyoj 12-喷水装置(二)(贪心)
12-喷水装置(二)
内存限制:64MB
时间限制:3000ms
Special Judge: No
accepted:10
submit:30
题目描述:
有一块草坪,横向长w,纵向长为h,在它的橫向中心线上不同位置处装有n(n<=10000)个点状的喷水装置,每个喷水装置i喷水的效果是让以它为中心半径为Ri的圆都被润湿。请在给出的喷水装置中选择尽量少的喷水装置,把整个草坪全部润湿。
输入描述:
第一行输入一个正整数N表示共有n次测试数据。 每一组测试数据的第一行有三个整数n,w,h,n表示共有n个喷水装置,w表示草坪的横向长度,h表示草坪的纵向长度。 随后的n行,都有两个整数xi和ri,xi表示第i个喷水装置的的横坐标(最左边为0),ri表示该喷水装置能覆盖的圆的半径。
输出描述:
每组测试数据输出一个正整数,表示共需要多少个喷水装置,每个输出单独占一行。 如果不存在一种能够把整个草坪湿润的方案,请输出0。
样例输入:
2 2 8 6 1 1 4 5 2 10 6 4 5 6 5
样例输出:
1 2
分析:
①、因为是圆组合成一条线的问题所以我们应该清晰认识到的是 --> 圆在该区域的有效长度 L = (sqrt(r^2 - (h/2)^2))
②、因为圆的有效长度为L,所以半径小于 (h/2) 的圆完全没有考虑的必要了(酱紫:要考虑的圆将会减少一定的数量)
步骤:
①、根据输入的位置坐标和半径情况构建出每个圆的有效区域,并将其存放在结构体中
②、从左到右遍历寻找一组这样的区域:“左端 小于 初始点” && “右端 大于 初始点” && “有端点的值最大”
③、将最大的右端点作为下一个初始点
④、循环 ②、③ 步,知道能够全部覆盖草坪或喷泉用完
核心代码:
1 double L_flag = 0, R_flag; 2 for(int i = 0; i < n; ++ i) 3 { 4 if(P[i].l <= L_flag) 5 { 6 R_flag = P[i].r; 7 while(P[i].l <= L_flag && i < n) 8 { 9 R_flag = max(P[i].r, R_flag); 10 ++ i; 11 } 12 -- i; 13 cnt ++; 14 L_flag = R_falg; 15 } 16 if (L_flag >= w) 17 { 18 printf("%d\n", cnt); 19 break; 20 } 21 }
C/C++代码实现(AC):
1 #include <iostream> 2 #include <algorithm> 3 #include <cmath> 4 #include <cstring> 5 #include <cstdio> 6 #include <queue> 7 #include <set> 8 #include <map> 9 #include <stack> 10 11 using namespace std; 12 13 struct node 14 { 15 double l, r; 16 } P[10010]; 17 18 bool cmp(node a, node b) 19 { 20 return a.l < b.l; 21 } 22 23 int main () 24 { 25 int t; 26 scanf("%d", &t); 27 while (t --) 28 { 29 int cnt = 0, n, flag = 0; 30 double w, h; // n 装置个数、 w长度、 h 高度 31 scanf("%d%lf%lf", &n, &w, &h); 32 for(int i = 0; i < n; ++ i) 33 { 34 double x, r, temp; 35 scanf("%lf%lf", &x, &r); 36 if (r > (h / 2)) 37 { 38 temp = sqrt(r * r - (h / 2) * (h / 2)); 39 P[i].l = x - temp; 40 P[i].r = x + temp; 41 } 42 else 43 { 44 P[i].l = x; 45 P[i].r = x; 46 } 47 } 48 sort(P, P + n, cmp); 49 50 double L_flag = 0.0, R_flag; 51 for(int i = 0; i < n; ++ i) 52 { 53 if(P[i].l <= L_flag) 54 { 55 R_flag = P[i].l; 56 while(P[i].l <= L_flag && i < n) 57 { 58 R_flag = max(R_flag, P[i].r); 59 ++ i; 60 } 61 -- i; 62 L_flag = R_flag; 63 cnt ++; 64 } 65 if(L_flag >= w) 66 { 67 flag = 1; 68 printf("%d\n", cnt); 69 break; 70 } 71 } 72 if(!flag) printf("0\n"); 73 } 74 return 0; 75 }