poj 1328 Radar Installation

/*

 

一般我们的做法都是正向思维,即先对横坐标排好序,再枚举横坐标的整点,

然后贪心做,其实这样做是很费力的。

 

可以逆向思维考虑一下:

   最多只有1000的点,我们可以先预处理完以该点为圆心,半径为d的圆与横坐标的左右交点

   (当然还可能只有1个,或者没有),然后分别储存到结构体的两个关键字中,然后尽量再枚举

   后面的点的区间与前面的点的区间(两个关键字构成的区间)有交集(贪心,因为事先排好序),

   再向后面延展的同时,使得雷达的数量最小化,直到遇到没有交集的点为止

   (我的文字可能不清晰,具体看代码)

 

*/

#include <cstdio>

#include <iostream>

#include <algorithm>

#include <cmath>

using namespace std;

#define X 1005

int n,d;

struct node

{

   double x,y;

   friend bool operator <(node a,node b)//重载符号,方便排序

   {

      if(a.x==b.x)

         return a.y<b.y;

      return a.x<b.x;

   }

}p[X];

int main()

{

   freopen("sum.in","r",stdin);

   freopen("sum.out","w",stdout);

   int cnt = 0;

   while(cin>>n>>d,n||d)

   {

      int ans = 0,x,y;

      double temp;

      int t;

      bool flag = true;

      if(d<0)            //若覆盖距离小于0,直接fold掉

         flag = false;

      for(int i=0;i<n;i++)

      {

         scanf("%d%d",&x,&y);

         if(flag)    //若之前已经不成立了,无需再插入到结构体中,剪枝

         {

            t = d*d-y*y;

            if(t<0||y<0)

            {

                flag = false;

                continue;

            }

            temp = sqrt(t*1.0);   //注意若t<0时会出错的

            p[i].x = x-temp;   //以改点为圆心以d为半径的圆与x轴的两个交点(可能为一个)

            p[i].y = x+temp;

         }

      }

      if(!flag)

         printf("Case %d: %d\n",++cnt,-1);

      else

      {

         sort(p,p+n);

         temp = p[0].y;  //它所能覆盖的最大x的坐标

         for(int i=1;i<n;i++)

         {

            if(p[i].x>temp)//如果后面的点的左边的值已经比它大,说明需要添加雷达,同时更新temp

            {

                ans++;

                temp = p[i].y;

            }

            else if(p[i].y<temp)//若后面的点的最大能覆盖到的距离比之前的还小,更新一下

                temp = p[i].y;

         }

         printf("Case %d: %d\n",++cnt,ans+1);

      }

   }

   return 0;

}

原文地址:https://www.cnblogs.com/yejinru/p/2433734.html