pku-1328 我的贪心

来源:互联网 发布:怎么用chorm调试js 编辑:程序博客网 时间:2024/05/21 18:41

  [ 题目描述] 假设有一条无限长的海岸线,在海的那一半有n个岛屿。在海岸线上有雷达,每个雷达能够探测的范围为半径为d的圆,一个岛屿能被雷达探测到,当且仅当它与雷达的距离小于等于d

    我们用直角坐标系来抽象这些,x轴为海岸线,x轴上面为海,x轴下面为陆地(如图)。

 3.2图

    给出所有岛屿的坐标和雷达的半径。求最少需要用多少个雷达,使得所有的岛屿都被探测到。(无解输出-1

    【分析】这道题目很容易想到用贪心的方法,找一个圆,并且这个圆覆盖得点越多越好。

    我们可以将所有的点用一种方法映射到x轴上,成为圆心。最容易想到的是垂直投影,这样x轴上的每一个点为圆心的圆一定可以覆盖正上方的岛屿,就可以使用贪心法了。但是这样做是错的,因为如果点的纵坐标小于d,则会造成圆的浪费,为了极大限度的利用圆(贪心思想),应该寻找每个点对应的圆心(点在圆上,圆心在点右侧)。再从左到右遍历一遍,就可以完美的解决问题。(引用http://liymouse.bokee.com/5017529.html)

//利用贪心思想解决

#include <iostream>
#include <cmath>
//--------------------------------
using namespace std;
typedef struct p
{
 int x;
 int y;
}point;

typedef struct b
{
 float left;
 float right;
}bound;

int compare(const void *p1,const void *p2)
{//used by qiuck sort
 bound a=*(bound *)p1;
 bound b=*(bound *)p2;
 if(a.left>b.left)
  return 1;
 else if(a.left==b.left && a.right>b.right)
  return 1;
 return -1;
}

int main()
{
 int i;

 int num=0;
 int n,d;
 point p[1000];
 bound b[1000];
 while(1)
 {
  int flag=0;
  num++;
  int count=1;
  cin >> n >> d;
  if(n==0 && d==0)
   exit(1);
  for(i=0;i<n;i++)
  {
   cin >> p[i].x >> p[i].y;
   float temp=sqrt((float) (d*d-p[i].y*p[i].y) );
   b[i].left=p[i].x-temp;
   b[i].right=p[i].x+temp;
   if(p[i].y>d)
    flag=1;
  }
  if(d<=0 || flag==1)
  {
   cout << "Case " << num << ": " << -1 << endl;
   continue;
  }
  qsort(b,n,sizeof(bound),compare);

  float right=b[0].right;
  for(i=1;i<n;i++)
  {
   if(b[i].left>right)
   {
    count++;
    right=b[i].right;
   }
   else if(b[i].right<right)
    right=b[i].right;
  }
  cout << "Case " << num << ": " << count << endl;
 }
 return 0;
}

原创粉丝点击