分享按钮

NYOJ 喷水装置(二)


喷水装置(二)

时间限制: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<iostream>
 2 #include<algorithm>
 3 #include <math.h> 
 4 using namespace std;
 5 #define max(a,b) (a>b?a:b)
 6 struct Ww{
 7   float xi,ri;
 8        };
 9 bool com(const Ww &a,const Ww &b){
10      if(a.xi<b.xi) return true;
11      if(a.xi==b.xi&&a.ri>b.ri) return true;
12      
13      return false;
14       
15      }
16 float dis(float rr,float hh){
17       if(rr*rr-hh*hh/4>=0)
18     return sqrt(rr*rr-hh*hh/4);  
19     else
20     return 0;
21       
22       }
23 
24 
25 int main(){
26 int m;
27 freopen("12.txt","r",stdin);
28 cin>>m;
29 while(m--){
30    int n;
31    cin>>n;
32    Ww a[n];
33    float w,h;
34    cin>>w;
35    cin>>h;
36    for(int i=0;i<n;i++)
37    cin>>a[i].xi>>a[i].ri;   
38    
39  sort(a,a+n,com);
40  
41  
42   
43  float sum=0;
44  int count=0;
45  int first=0,rear=n-1;
46  
47  for(int i=0;i<=n-1;i++){
48    
49           if(rear==first&&(a[first].ri>=sqrt(w/2+h*h/4))) { count++; break;                   
50                           } 
51           if(rear==first&&a[first].ri<sqrt(w/2+h*h/4)) {break;}
52           
53          if(dis(a[first].ri,h)>=a[first].xi){
54           if(dis(a[rear].ri,h)>=w-a[rear].xi)     {                             
55            if(a[i].xi!=a[i+1].xi){           
56           if(dis(a[i].ri,h)+dis(a[i+1].ri,h)>=a[i+1].xi-a[i].xi){
57            if(first==i) count+=2;
58            else
59            count++;
60            
61            
62            }}
63      
64            }else{
65                  rear--;
66                  }
67            
68            
69            }else 
70            {
71                 first++;
72                 }
73                 
74                     }
75 
76      
77  cout<<count<<endl;
78            }
79 
80       
81 }

 

我后来重写的:
 1 #include<stdio.h>
 2 #include<string.h>
 3 #include<math.h> 
 4 #include<algorithm>
 5 using namespace std;
 6 struct ps
 7 {
 8     double left; 
 9     double right; 
10 }w[10001];
11 bool comp(ps a,ps b) 
12 {
13     if(a.left<b.left) return true;
14     return false;
15 }
16 int main()
17 {
18        freopen("12.txt","r",stdin);
19     int ncases,n,i,width,high,x,r,count,flag;
20     double length,sum,max;
21     scanf("%d",&ncases);
22     while(ncases--)
23     {
24         flag=1;sum=0;count=0;
25         scanf("%d %d %d",&n,&width,&high);
26         for(i=0;i<=n-1;i++) 
27         {
28             scanf("%d %d",&x,&r);
29             length=(double)r*r-(double)high/2*high/2;
30             if(length>=0) {length=sqrt(length);} 
31             if(length<0) {length=0;} 
32             w[i].left=x-length;
33             w[i].right=x+length;
34         }
35         sort(w,w+n,comp);
36         while(sum<width) 
37         {
38             max=0; 
39             for(i=0;i<=n-1&&w[i].left<=sum;i++) 
40             {
41                 if((w[i].right-sum)>max) 
42                 {
43                     max=w[i].right-sum; 
44                 }
45             }
46             if(max==0) 
47             {
48                 flag=0;
49                 break;
50             }
51             else
52             {
53                 sum=sum+max; 
54                 count++;
55             }
56         }
57         if(flag==1)
58         {
59             printf("%d\n",count);
60         }
61         else
62         {
63             printf("0\n");
64         }
65     }
66     return 0;
67 }

 

最优程序:
 1  
 2 #include<iostream>
 3 #include<vector>
 4 #include<algorithm>
 5 #include<cmath>
 6 using namespace std;
 7 double r,x,y,width,height;
 8 class Circle
 9 {
10 public:
11     Circle(double x,double r):x(x),r(r){}
12     double Left() const{
13         if(r*r-height*height/4<0) return x;return x-sqrt(r*r-(height*height/4));}
14     double Right() const{if(r*r-height*height/4<0) return x;return x+sqrt(r*r-(height*height/4));}
15     friend ostream & operator<<(ostream& out,const Circle& circle);
16 private:
17     double x,r;
18 };
19 ostream & operator<<(ostream& out,const Circle& circle)
20 {
21     out<<circle.x<<" "<<circle.r;
22     return out;
23 }
24 struct CircleLess
25 {
26     bool operator()(const Circle& c1,const Circle& c2)
27     {
28         return c1.Right()<c2.Right();
29     }
30 };
31 
32 int main()
33 {
34 
35     int m;
36     cin>>m;
37     while(m--)
38     {
39         int n;
40         
41         vector<Circle> Rs;
42         cin>>n>>width>>height;
43         Rs.reserve(n);
44         
45         
46         while(n--)
47         {
48             cin>>x>>r;
49             Rs.push_back(Circle(x,r));
50         }
51         sort(Rs.begin(),Rs.end(),CircleLess());
52         vector<int> choosed;
53         choosed.push_back(-1);
54         double len=0;
55         try{
56             while(len<width)
57             {
58                 int last=-1;
59                 for(vector<Circle>::size_type i=choosed.back()+1;i!=Rs.size();i++)
60                 {
61                     if (Rs[i].Left()<=len)
62                     {
63                         //cout<<Rs[i].Left()<<endl;
64                         last=i;
65                     }
66                 }
67                 if (last==-1) throw -1;
68                 else
69                 {
70                     choosed.push_back(last);
71                     len=Rs[last].Right();
72                 }
73             }    
74             cout<<choosed.size()-1<<endl;
75         
76         }catch(...)
77         {
78             cout<<0<<endl;
79         }
80     }
81 
82 }                             

 

posted @ 2012-05-05 00:00  草莓在努力  阅读(1063)  评论(0编辑  收藏  举报