POJ - 1328 Radar Installation(贪心/最大不相交覆盖)

问题描述
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.

POJ - 1328 Radar Installation(贪心/最大不相交覆盖)_第1张图片
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

分析

先解释一下这个题目,意思就是在x轴上安放雷达,每一个雷达覆盖的范围是一个以d为半径的圆。在海上(y>0)的区域内有n个岛屿,要求安放最少的雷达覆盖所有的岛屿。

首先我自己分析这个题目的时候想到了POJ-3069这个题目,题目大意就是在一条直线上(一维空间),有多个点,然后给它们加上标记,对每个点,其距离为R以内的区域内必须有标记的点,求最少的标记点数目。想了半天啊,发现根本不是这个思路,虽然也相当于在x轴这条线上找标记点,但是它覆盖的区域是二维空间里的点,这样无法按照一维的先排序再贪心。

所以换思路,它要求在x轴上找点作为雷达,这个点肯定在一个区间内都可以覆盖到某个岛屿,那么就利用一下简单的平面几何知识,以岛屿为圆心,d为半径画圆,交于x轴两点,那么这两点就是雷达可覆盖到此岛屿的区间范围,那么把所有的岛屿都如此操作,并将区间存放,这样如果有多个岛屿的区间有相交的部分,那么雷达就可以放在相交的区间内,这样此雷达就可以覆盖到多个岛屿了,也就转换为最大不相交覆盖问题。

注意,如果d < 0 , 或者一个岛屿的y<0(题目要求岛屿只能在海域) ,或者某个岛屿的y > d(这样x轴上不可能有雷达能覆盖到此岛屿),这些情况都是无法解决的,输出-1。PS:在这上面wa了好多次。

#include
#include
#include
using namespace std;
const int maxn = 1000+10;
int n, d;
struct Island{
    double x,y;
}island[maxn];

struct Interval{
    double start, end;
}a[maxn];

int cmp(const Interval &a, const Interval &b)
{
    if(a.end < b.end) return 1;
    else if(a.end == b.end && a.start < b.start) return 1;
    else return 0;
}
/*找圆与x轴交点的左端点*/
double left_x(double x, double y)
{
    double x_len = sqrt(d*d - y*y);
    return x-x_len;
}
/*找圆与x轴交点的右端点*/
double right_x(double x, double y)
{
    double x_len = sqrt(d*d - y*y);
    return x+x_len;
}
/*最大不相交覆盖的解决*/
void solve()
{
    sort(a, a+n, cmp);
    double e = a[0].start - 1;
    int count = 0;
    for(int i=0; iif(a[i].start > e)  
        {
            count++;
            e = a[i].end;
        }
    }
    printf("%d\n",count);
    return;
}

int main()
{
    int k = 0;
    while(scanf("%d%d",&n, &d)!=EOF)
    {
        int ok = 1;
        if(n == 0 && d == 0) break;
        for(int i=0; iscanf("%lf%lf",&island[i].x, &island[i].y);
            if(island[i].y > d || island[i].y < 0) ok = 0;//注意细节
            a[i].start = left_x(island[i].x, island[i].y);
            a[i].end = right_x(island[i].x, island[i].y);
        }   
        if(!ok)
        printf("Case %d: -1\n",++k);
        else{
            printf("Case %d: ",++k);
            solve();
        }
    }   
    return 0;
}

你可能感兴趣的:(POJ,贪心)