POJ1328 Radar Installation(贪心)

来源:互联网 发布:wps的数据有效性在哪 编辑:程序博客网 时间:2024/06/05 19:57

Description

Assume the coasting is an infinite straight line. Land is in one side of coasting, sea in the other. Each small island is a point locating in the sea side. And any radar installation, locating on the coasting, can only cover d distance, so an island in the sea can be covered by a radius installation, if the distance between them is at most d. 

We use Cartesian coordinate system, defining the coasting is the x-axis. The sea side is above x-axis, and the land side below. Given the position of each island in the sea, and given the distance of the coverage of the radar installation, your task is to write a program to find the minimal number of radar installations to cover all the islands. Note that the position of an island is represented by its x-y coordinates. 
 
Figure A Sample Input of Radar Installations


Input

The input consists of several test cases. The first line of each case contains two integers n (1<=n<=1000) and d, where n is the number of islands in the sea and d is the distance of coverage of the radar installation. This is followed by n lines each containing two integers representing the coordinate of the position of each island. Then a blank line follows to separate the cases. 

The input is terminated by a line containing pair of zeros 

Output

For each test case output one line consisting of the test case number followed by the minimal number of radar installations needed. "-1" installation means no solution for that case.

Sample Input

3 21 2-3 12 11 20 20 0

Sample Output

Case 1: 2Case 2: 1

Source

Beijing 2002
题目链接:poj1328

         首先这个题的题意就是在一个平面坐标内,有n个处于x轴上方的点,作为岛屿。在X轴上可以安放雷达,雷达的半径为d。题目要求根据n个岛屿的坐标和雷达的半径d求解出最少需要多少个雷达才嫩把所有的岛屿包括进来。如果没有办法把所有的包括进来,则出输出-1.
         第一次看到这个题我的想法和后来在网上找的差不多,我想的是将每个坐标(x0,y0)与X轴的交点求出来,求法是勾股定理x=x0-根号下(d²-y0²),然后画出一个区间[xd,yd],比较这n个岛屿的区间之间是否存在重叠,若存在则安装一个雷达。
        但是后来想了想可行度不高,于是看了下网上的解析,其实就是一个数据结构设置的不当的问题,网上是将每个点与X轴的左右交点存储在一个结构体数组中,然后排序,比较左右两岛屿的左右两个交点的左右关系。并用temp来标记稍微靠右边的那个点,用p[i]来更新新的点,直到temp.right<p[i].left为止,再让temp=p[i],进行新的比较。还是这种方法比较好实现。
下面是代码和一部分解析。(转载)

图中ABCD为海岛的位置。假设本题半径为2(符合坐标系),那么A点坐标为(1,1)以此类推。

在题中,记录每个点的坐标,并把一个点新加一个标记变量以标记是否被访问过。

首先以A为圆心,r为半径做圆,交x轴与E1(右)点,做出如图中绿色虚线圆。然后以E1为圆心,半径为r做圆。看此时下一点(B)是否在该圆中。如果在,那么将该点标记变量变为true,再判下一点(C),如果不在那么就新增一个雷达。

后来,换了思路,存储图中红色圆与X轴的交点。

还是原来的贪心思路,仍然先排序,但排序的准则是按红色圆与x轴左交点的先后顺序。

如图,如果B点圆(且如此称呼)的左交点(J1点)在A点圆右交点(E1)左侧,那么B点一定涵盖在A点圆内部。再如图,如果D点圆的左交点(图中未标示)在A点圆的右交点(未标示)右,则D点不在A点圆中。

故,有如下代码:

#include <iostream>  #include <algorithm>  #include <stdlib.h>  #include <math.h>    using namespace std;    struct point  {      double left, right;  }p[2010], temp;    bool operator < (point a, point b)  {      return a.left < b.left;  }    int main()  {      int n;      double r;      int kase = 0;      while (cin >> n >> r && (n || r))      {          bool flag = false;          for (int i = 0; i < n; i++)          {              double a, b;              cin >> a >> b;              if (fabs(b) > r)              {                  flag = true;              }              else              {                  p[i].left = a * 1.0 - sqrt(r * r - b * b);                  p[i].right = a * 1.0 + sqrt(r * r - b * b);              }          }          cout << "Case " << ++kase << ": ";          if (flag)          {              cout << -1 << endl;          }          else          {              int countt = 1;              sort(p, p + n);              temp = p[0];                            for (int i = 1; i < n; i++)              {                  if (p[i].left > temp.right)                  {                      countt++;                      temp = p[i];                  }                  else if (p[i].right < temp.right)                  {                      temp = p[i];                  }              }              cout << countt << endl;          }      }  }  


原创粉丝点击