POJ1328 Radar installation

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Fitz1318/article/details/86258835

题目链接:http://poj.org/problem?id=1328

大致题意:给定一个直角坐标系,定义x轴为海岸线,海岸线上方是海,下方是陆地。在海域零星分布一些海岛, 需要要在海岸线上安装若干个雷达覆盖这些海岛。每个雷达的覆盖半径都是相同且固定。现在给定所有海岛的坐标(x,y), 以及雷达的覆盖半径d,求可以覆盖所有海岛的最小雷达数。若没有则输出-1

解题思路:

①只要存在任意一个海岛位置超出雷达最大覆盖半径(即y>d),则无解。

②当y<d时,以海岛坐标(x,y)为圆心,用雷达覆盖半径d画圆,根据前提条件可知,这个圆与x轴必定存在最少1个(y=d)、最多2个交点(y<d)。可以认为1个交点是2个交点重合的特殊情况,那么这2个交点在x轴上构成的线性区间,可以看作海岛的被覆盖范围在x轴上的投影 (由此就可以把二维的几何问题转化成一维几何问题)。 

③按照所有海岛的x轴坐标,从小到大依次计算每个海岛在x轴上的投影区间(投影可能存在重叠),同时把每个雷达抽象成1个点,那么此问题就转化成:已知x轴上若干个区间(可能存在交集),现在要往这些区间内放若干个点,问怎样放置这些点,使得每个区间内至少存在一个点,且所放置的点的总量尽可能最少。

算法如下:

首先根据每个区间的左端点坐标对所有区间从左到右排序。

①在左起第一个区间A 的右端点 A.right 放置一个点,总放置点数 num+1

②若下一个区间B 的左端点 B.left > A.right, 说明 区间A 与 区间B 无交集,此时在区间B 的右端点 B.right 放置一个点,总放置点数 P+1 。否则说明 区间A 与 区间B 相交。此时进一步判断,若 B.right< A.right,说明 区间B 在 区间A 的内部,此时把原本放置在 A.right 的点移动到 B.right(确保区间B有一个点),总放置点数不变

③ 重复这个过程直到所有区间被遍历完成

PS:这里要注意使用scanf输入,而不要用cin输入,cin会超时。。。。

AC代码:

#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>

using namespace std;

struct Inteval {
    double left;//区间左端点
    double right;//区间右端点
};

bool cmp(Inteval a, Inteval b)
{
    return a.left <= b.left;
}
int solve(Inteval *intevals, int nums)
{

    int MinPoints = 1;
    double right = intevals[0].right;
    for(int i = 1; i < nums; i++) {
        //区间i+1与区间i无交集
        if(intevals[i].left > right) {
            MinPoints++;
            right = intevals[i].right;
        }
        //区间i+1在区间i内部//区间i+1与区间i相交
        else if(intevals[i].right < right) {
            right = intevals[i].right;
        }
    }
    return MinPoints;
}

int main()
{
    int islands, r, testCase = 1;
    while((scanf("%d%d", &islands, &r) != EOF) && islands && r) {
        double R = r * r;
        Inteval *intevals = new Inteval[islands];
        bool flag = true;//flag作为能否解决的标志
        for(int i = 0; i < islands; i++) {
            double x, y;
            scanf("%lf%lf", &x, &y);
            if(y > r) {
                flag = false;
            }
            double offset = sqrt(R - y * y);
            intevals[i].left = x - offset;
            intevals[i].right = x + offset;
        }
        sort(intevals, intevals + islands, cmp);
        int MinRadar = (flag ? solve(intevals, islands) : -1);
        cout << "Case " << testCase++ << ": " << MinRadar << endl;
        delete[] intevals;
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/Fitz1318/article/details/86258835