贪心问题:区间覆盖 POJ 1328 Rader Installation

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

题意:给定海岛个数,雷达半径,输入各个海岛坐标,求能覆盖所有海岛的最少雷达数

题解:

1. 贪心的区间覆盖问题,尽量让每个雷达覆盖更多岛屿数。

2. 需要将题目转换一下,将海岛坐标,转换为,能够覆盖他的所有雷达圆心的区间, 然后对区间按照起点位置升序排序。

3. 定义一个最右点 end,依次判断所有区间,如果 end < sec[i].start,更新雷达位置,雷达数++;否则如果 end > sec[i].end,更新雷达位置end为sec[i].end。

#include <iostream>
#include <algorithm>
#include <cstdlib>
#include <cstdio>
#include <cmath>
#include <limits>
using namespace std;

int n, d;
const int maxn = 1024 + 20;
struct Section {
    double start,
           end;
    Section(double s = 0, double e = 0) : start(s), end(e) {}
} sec[maxn];

bool cmp(const Section& a, const Section& b) {
    return a.start < b.start;
}

void solve()
{
    int kase = 0;
    while (cin >> n >> d && n)
    {
        bool flag = true;           //false: 不能构成 
        int ans = 0;
        for (int i = 0; i < n; i++)
        {
            double x, y;
            cin >> x >> y;
            if (!flag) continue;   //前面数据就已经不符合了,没必要再输入了 
            if (y > d)
            {
                //y比半径大,一定不可以
                flag = false;
                continue;   //继续输入    
            } 
            double dis = sqrt(d * d - y * y); 
            //能覆盖它的所有雷达的圆心所构成的区间 
            sec[i].start = x - dis;   
            sec[i].end = x + dis; 
        }
        if (!flag) 
        {
            printf("Case %d: -1
", ++kase);
            continue;    
        }
        sort(sec, sec + n, cmp);
        
        //求double最小值 
        double end = -numeric_limits<double>::max();
        for (int i = 0; i < n; i++)
        {
            if (end < sec[i].start) {
                ans++;
                end = sec[i].end;
            }
            else if (end > sec[i].end) {
                end = sec[i].end;
            }
        }
        printf("Case %d: %d
", ++kase, ans);
    }
}

int main()
{
    solve();
    
    return 0;    
}
原文地址:https://www.cnblogs.com/douzujun/p/8481691.html