首页 > 代码库 > uva--10382Watering Grass+贪心

uva--10382Watering Grass+贪心

题意:

   一片长为L宽为W的矩形草坪,然后给出n个喷头的圆心坐标和半径,问你最少需要几个喷头可以覆盖整个草坪。

思路:

  刚开始的时候直接觉得可以算出每个喷头可以覆盖的区间,然后就变成前面刚做过的区间覆盖问题了;后面看了一下样例,发现这样想是不对的,因为喷头边沿的圆弧可能是不能完全覆盖住草地的,所以那些地方就必须还要别的喷头去覆盖,这样就不能直接用区间合并来做了。后面又想了一下,其实每个喷头覆盖的有效区域就是一个矩形,我们只需要求出每个喷头覆盖的有效区域(就是矩形完全包含在圆内的部分,用简单的几何知识算一下就可以得到的),就又变成区间覆盖问题了!有一点需要注意:如果一个喷头的半径不大于矩形宽度一半的话,那么这个喷头可以覆盖的有效区域为0(相当于这个矩形的内接圆),我们可以忽略这些喷头。


代码如下:


#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;

typedef struct
{
       double x,y;
}P;
P p[11000];

int cmp(P p1,P p2)
{
       return p1.x<p2.x;
}

int main()
{
       int i,j,k,n;
       double len,w;
       while(scanf("%d%lf%lf",&n,&len,&w)!=EOF)
       {
                k=0;
                for(i=0;i<n;i++)
                {
                      double x1,r;
                      scanf("%lf%lf",&x1,&r);
                      if(r<=w/2)
                             continue;
                      p[k].x=x1-sqrt(r*r-w*w/4);
                      p[k].y=x1+sqrt(r*r-w*w/4);
                      k++;
                }
                sort(p,p+k,cmp);
                int cnt=0,flag=0;
                double left=0;
                for(i=0;i<k;)
                {
                      double max1=0;
                      while(p[i].x<=left&&i<k)
                      {
                              if(p[i].y>max1)
                                  max1=p[i].y;
                              i++;
                      }
                      if(max1==0)
                          break;
                      cnt++;
                      left=max1;
                      if(left>=len)
                     {
                            flag=1;
                            break;
                     }
                }
                if(flag)
                     printf("%d\n",cnt);
                else
                     printf("-1\n");
       }
   return 0;
}




uva--10382Watering Grass+贪心