nyoj 题目12 喷水装置(二)

喷水装置(二)

时间限制:3000 ms  |  内存限制:65535 KB
难度:4
 
描述
有一块草坪,横向长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

有些代码还是得自己想,别人的还是看不懂。
先上代码
 1 #include <cstdio>
 2 #include <algorithm>
 3 #include <cmath>
 4 using namespace std;
 5 typedef pair<double,double> Segment;
 6 
 7 Segment seg[10002];
 8 
 9 Segment getSeg(int x, int r, int h2) {
10     int p = r*r - h2*h2;
11     double d = sqrt(p);
12     double x0 = (double)x;
13     Segment tmp(x0-d,x0+d);
14     return tmp;
15 }
16 
17 int cmp(const void *a, const void *b) {
18     Segment at = *(Segment*)a;
19     Segment bt = *(Segment*)b;
20     return at.first - bt.first;
21 }
22 
23 int main(int argc, char const *argv[])
24 {
25     int t;
26     scanf("%d",&t);
27     while(t--) {
28         int n,w,h;
29         scanf("%d %d %d",&n,&w,&h);
30         int cnt = 0;
31         int h2 = h/2;
32         while(n--){
33             int x,r;
34             scanf("%d %d",&x,&r);
35             if(r <= h2) {
36                 continue;
37             }
38             seg[cnt++] = getSeg(x,r,h2);
39         }
40         qsort(seg, cnt, sizeof(Segment),cmp);
41         int to = 0;
42         int p = 0;
43         int ans = 0;
44         while(to < w) {
45             int j = p;
46             int maxTo = to;
47             while(j < cnt && seg[j].first <= to) {
48                 if(maxTo < seg[j].second) {
49                     maxTo = seg[j].second;
50                 }
51                 j++;
52             }
53             if(j == p) {
54                 break;
55             }
56             ans++;
57             to = maxTo;
58             p = j;
59         }
60         printf("%d
",ans);
61     }
62     return 0;
63 }

思路还是要转换成水平方向上的覆盖。这里要用到贪心的思想。

中心思想就是,选择一个可以覆盖到当前末端并且覆盖最大的线段

原文地址:https://www.cnblogs.com/jasonJie/p/6086677.html