uva10382 - Watering Grass

题目大意:输入n,l,w.分别代表有n个喷水装置,草地长为L,宽为W;接下来n行,每行两个数,a,r,分别代表喷水装置在草地中的横坐标,和喷水半径。喷水装置的纵坐标都是草地的正中央。求用最少的喷水装置洒水,覆盖所有的草地,若不能输出-1,能则输出所需的最少的喷水装置数目。

题目解析:排序+贪心,恶心的是卡了精度!输入时计算出所有喷水装置能覆盖的横坐标的范围。已知圆的半径和弦长,则可以求出圆心到弦长的距离s,用圆心的位置a-s则可得当前喷水装置能覆盖的最左边的的草地,a+s,表示能覆盖的最右边的草地坐标。然后以最左边的覆盖范围为依据排序,然后贪心满足条件的能覆盖到最右边的喷水装置。

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<math.h>
#define MAX 100010
typedef struct node
{
        double L,R;       
}node;
node map[MAX];
const double INF=10e-9;
int n,l,w;
int cmp(const void *aa,const void *bb)
{
    node *a=(node *)aa;
    node *b=(node *)bb;
    if (a->L!=b->L)
       return a->L > b->L ?1:-1;
    return a->R > b->R ?1:-1;
}
int main()
{
    while (scanf("%d%d%d",&n,&l,&w)!=EOF)
    {
          
          int i,j=0,a,r,m=0;
          double ans,cnt;      
          for (i=0;i<n;i++)
          {
              scanf("%d%d",&a,&r);
              if (r*2>w)
              {
                 ans=sqrt((double)r*r-(double)w*w/4.0);
                 map[j].L=(double)a-ans;
                 map[j++].R=(double)a+ans;                 
              }
          }
          qsort(map,j,sizeof(node),cmp);
          cnt=ans=0.0;
          for (i=0;i<j;i++)
          {
              int flag=0,tot=0;
              cnt=ans;
              while (map[i].L-cnt<INF&&i<j)
              {
                    if (map[i].R>ans)
                    {
                       ans=map[i].R; 
                       tot=1;                
                    }        
                    i++;
                    flag=1;  
              }
              if (flag)
              {
                 i--;
              }
              if (tot)
                 m++;
              if (ans>l)
                 break;
          }
          if (ans>=l)
             printf("%d\n",m);
          else
             printf("-1\n"); 
    }
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值