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 }

 


posted @ 2018-05-16 22:30  GetcharZp  阅读(320)  评论(0编辑  收藏  举报