欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

POJ1328 Radar Installation(贪心)

程序员文章站 2022-03-26 14:07:27
...

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. 
POJ1328 Radar Installation(贪心) 
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 2
1 2
-3 1
2 1

1 2
0 2

0 0

Sample Output

Case 1: 2
Case 2: 1

Source

题目链接: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],进行新的比较。还是这种方法比较好实现。
下面是代码和一部分解析。(转载)
POJ1328 Radar Installation(贪心)

图中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;  
        }  
    }  
}  


相关标签: 贪心