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

思路:看到此题大多数人都会知道是贪心问题,但是由于这个题每个喷泉的位置和半径都不相同,所以直接贪心不太好实现,因为每个喷泉足够长度与边都有左右两个交点,我们通过对左右坐标的贪心来实现,由勾股定理可知,x*x=r*r-h*h/4; 小于0的不符合题意,直接舍去,然后左坐标进行升序排序,左坐标相等,按右坐标从大到小排序;最后输出结果;  如果第一个最小的左交点不是<=0则一定不满足;

ac代码:

#include

#include

#include

#include
using namespace std;
struct ff{
double l;
double r;
}a[1010];
bool cmp(struct ff a,struct ff b)
{     if(a.l==b.l)
       return a.r>b.r;
      else
       return a.l
}
int main()
{   int t,n,i,j,count;
     double h,w,x,r,begin,end;//数据类型要搞清楚
 cin>>t;
   while(t--)
   {   cin>>n>>w>>h;
       h/=2;
       a[1010]={0};
       for(i=0,j=0;i
       {   cin>>x>>r;
           double t=r*r-h*h;
           if(t>0)//小于0的不满足题意
           {    a[j].l=x-sqrt(t);//与边交点的左右坐标
                a[j].r=x+sqrt(t);
                j++; 
  }
  }
  sort(a,a+j,cmp);
  if(a[0].l>0) 
    cout<<0<
  else
  {   begin=end=0;
      i=count=0;
      while(end<=w&&i
      {    while(a[i].l<=begin&&i
           {  if(a[i].r>=end)  
               end=a[i].r;
               i++;
    }
  begin=end;
  count++;}
  if(endn)
   cout<<0<
  else
   cout<
  }
   
   }
   return 0;
}

你可能感兴趣的:(nyoj,贪心)