贪心算法训练(六)——喷水装置(区间覆盖问题)

贪心算法训练(六)——喷水装置(区间覆盖问题)

1. 问题描述

  长 L 米,宽 W 米的草坪里装有 n 个浇灌喷头,每个喷头都装在草坪的中心线上(离两边各 W/2 米)。我们知道每个喷头的位置(离草坪中心线左端的距离),以及它能覆盖到的浇灌范围。请问如果要同时浇灌整块草坪,最少需要打开多少个喷头?

2. 输入格式

  输入包含若干测试数据

  每组数据的第一行是整数n、L 和 W 的值,其中 n <= 10000

  接下来的 n 行,每行包含 2 个整数,给出一个喷头的位置 x 和浇灌半径 r

3. 输出格式

  对每组测试数据输出一个数字,表示要浇灌整块草坪所需喷头数目的最小值。如果所有喷头都打开还不能浇灌整块草坪,则输出 -1

4. 样例输入

3
8 20 2
5 3
4 1
1 2
7 2
10 2  
13 3  
16 2
19 4
3 10 1
3 5
9 3
6 1
3 10 1
5 3
1 1
9 1

5. 样例输出

6
2
-1

6. 思路分析

  录入数据的同时计算出它的有效灌溉半径(勾股定理),start = x - sqrt(r^2 - (w/2)^2),end = x + sqrt(r^2 - (w/2)^2),排序,在选定位置范围内,依次寻找最大的 end。

7.代码(直接复制数据可能有问题,建议手动输入)

#include 
#include 
#include 
#include 
#include 

using namespace std;

int n,cnt,L,h,x,r;
struct SEG
{
    double x,y;
}a[20005];

bool cmp(const SEG& x,const SEG& y)
{
    return x.x < y.x;
}

void Read()
{
    cin>>n>>L>>h;
    cnt = 0;
    for(int i = 1;i <= n;i++)
    {
        cin>>x>>r;
        if(r <= h/2)
            continue;
        cnt ++;
        a[cnt].x = x - sqrt(r*r - h*h/4.0);
        a[cnt].y = x + sqrt(r*r - h*h/4.0);
    }
}

void solve()
{
    double t= 0;
    int ans = 0,bj = 1,i = 1;
    while(t < L)
    {
        ans ++;
        double s = t;
        for(;a[i].x <= s && i<= cnt;i++)
            if(t < a[i].y)
            t = a[i].y;
        if(t == s && s < L)
        {
            cout<<-1<<endl;
            bj = 0;
            break;
        }
    }
    if(bj)
        cout<endl;
}

int main()
{
    ios::sync_with_stdio(false);
    int T;
    cin>>T;
    while(T--)
    {
        Read();
        sort(a+1,a+cnt+1,cmp);
        solve();
    }
    return 0;
}

 

posted @ 2018-08-11 16:15 Nikki_o3o 阅读( ...) 评论( ...) 编辑 收藏

你可能感兴趣的:(贪心算法训练(六)——喷水装置(区间覆盖问题))