UVA10382喷水装置

题意:
      给你一个矩形的空地,然后有一些圆形的喷水装置,每个装置的圆心都在矩形宽的中间位置,然偶给你每个矩形的圆心位置和半径,问你最少多少个喷水装置可以把矩形的所有编辑都覆盖上。

思路:
      首先我们要把所有的圆都处理成矩形,也就是每个圆的最大覆盖矩形范围(除了矩形的部分,其他部分没意义,因为只有矩形能接壤上,不然会有空隙),然后变成了最小区间覆盖问题,最小区间覆盖问题可以用贪心的方式处理,刚做完UVA10020就是有一个单纯的求最小区间覆盖,那个题解刚写完,我直接把那个题解粘贴过来吧:

    大体思路可以是这样,我们先把所有的区间按照起点从小到大排序,然后我们定义一个当前覆盖位置pos,初始是0,也就是[0,m]的最左端,然后我们从小区间中找到一个可以覆盖pos点并且右端点最远的一个(记得sum++),然后把最远的这个右端点作为当前的pos,继续找下一个,至于实现,我是自己写的,可能写的不是很简洁,不知道网上有没有简洁点的,如果没有就讲究看下我的吧,具体细节看代码。


#include<math.h>
#include<stdio.h>
#include<algorithm>

#define N 11000


using namespace std;


typedef struct
{
   double l ,r;
}EDGE;

EDGE edge[N];

bool camp(EDGE a ,EDGE b)
{
   return a.l < b.l;
}

int main ()
{
   int n ,l ,w ,i;
   double x ,r;
   while(~scanf("%d %d %d" ,&n ,&l ,&w))
   {
      double w2 = w * 1.0 / 2;
      int nowid = 0;
      for(i = 1 ;i <= n ;i ++)
      {
         scanf("%lf %lf" ,&x ,&r);
         if(r <= w2) continue;
         double tmp = sqrt(r * r - w2 * w2);
         double ll = x - tmp ,rr = x + tmp;
         if(rr < 0 || ll > l) continue;
         nowid ++;
         edge[nowid].l = ll ,edge[nowid].r = rr;
      }
      sort(edge + 1 ,edge + nowid + 1 ,camp);
      int Ans = 0;
      double pos = 0 ,max = 0;
      for(i = 1 ;i <= nowid ;i ++)
      {
         if(pos > edge[i].r) continue;  
         if(edge[i].l <= pos)
         {
            if(max < edge[i].r) max = edge[i].r;
            if(i == nowid)
            {
               if(max < l){Ans = -1 ;break;}
               Ans ++;
            }
         }
         else
         {
            if(max == 0){Ans = -1 ;break;}
            pos = max;
            if(pos >= l) break;
            max = 0 ,Ans ++ ,i --;
         }
      }
      if(!Ans) Ans = -1; 
      printf("%d " ,Ans);
   }
   return 0;
}
         
          

原文地址:https://www.cnblogs.com/csnd/p/12062663.html