Uva 10382 Watering Grass

题意:给一个长宽:l*w的矩形,然后在w/2这条线上有n个点,以这些点为圆心,ri为半径,选择尽量少的点,覆盖这个矩形

题解:不能只有用圆去求,应当把每个圆转化成矩形去求,即转化为区间覆盖问题

1.把每个圆转化为小矩形,然后求出左右端点

2.以左端点和右端点排序

3.贪心循环去找

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define db double
 4 struct st{
 5         db p,r;
 6         db left, right;
 7 };
 8 st a[10000+20];
 9 bool cmp(st a, st b)
10 {
11         if(a.left!=b.left) return a.left<b.left;
12         return a.right<b.right;
13 }
14 int main()
15 {
16         int n;
17         ios::sync_with_stdio(false);
18         db l,w;
19         while(cin >> n >> l >> w)
20         {
21                 int j = 0;
22                 for(int i = 0;i < n;i++)
23                 {
24                         db x,y;
25                         cin >> x >> y;
26                         if(w>2*y) continue;
27                         a[j].p = x; a[j].r = y;
28                         a[j].left = x - sqrt( y*y - ((w/2)*(w/2)) );
29                         if(a[j].left<0) a[j].left=0;
30                         a[j].right = x + sqrt( y*y - ((w/2)*(w/2)) );
31                         if(a[j].right>l) a[j].right=l;
32                         j++;
33                 }
34                 int m = j;
35                 sort(a,a+m,cmp);
36                 if(a[0].left>0) {cout << "-1" << endl;continue;} //如果最左端点都不能覆盖0
37                 db mx = a[0].right;
38                 int i = 1;
39                 while(a[i].left == 0)i++; //找到覆盖0并且右端点最远的
40                 mx = a[i-1].right;
41                 int ans=1;
42                 while(1)
43                 {
44                         if(i>=m||mx==l) break; //m个点,或者覆盖了l,退出while
45                         db pp = mx;
46                         int flag=0,f=0;
47                         while(a[i].left<=pp) //找每一个左端点在上一个点最右端的里面的所有点
48                         {    f=1;
49                              if(a[i].right>mx){
50                                 mx = a[i].right; //更新mx
51                                 flag=1;
52                              }
53                              i++;
54                              if(i>=m||mx==l) break;
55                         }
56                         if(flag) ans++; //如果更新了,则多了一个点
57                         if(f==0) i++;//防死循环
58                 }
59                 if(mx==l) cout << ans << endl;
60                 else cout << "-1" << endl;
61         }
62 }

 

posted on 2015-11-23 22:36  小松song  阅读(99)  评论(0)    收藏  举报

导航