Watering Grass (uva - 10382)

Watering Grass

n sprinklers are installed in a horizontal strip of grass l meters long and w meters wide. Each sprinkler
is installed at the horizontal center line of the strip. For each sprinkler we are given its position as the
distance from the left end of the center line and its radius of operation.
What is the minimum number of sprinklers to turn on in order to water the entire strip of grass?
在这里插入图片描述
Input
Input consists of a number of cases. The first line for each case contains integer numbers n, l and w
with n ≤ 10000. The next n lines contain two integers giving the position of a sprinkler and its radius
of operation. (The picture above illustrates the first case from the sample input.)

Output
For each test case output the minimum number of sprinklers needed to water the entire strip of grass.
If it is impossible to water the entire strip output ‘-1’.

Sample Input
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
Sample Output
6
2
-1

题意就是给出一块矩形草坪的长和宽,然后给出一系列水管的水平位置以及水管洒水可以覆盖的区域的半径;每个水管可安装的地点都是草坪的纵向中心处,问最少需要几个水管可以使所有草坪都能被水覆盖到,输出最少数量;如果不能被覆盖全输出-1

我们需要知道每个水管覆盖范围与草坪交界的左右短点,然后存入结构,以便后面贪心排序
存的时候需要注意,虽然题中水管半径r是int型,但是如果数据非常大,平方的时候会爆,题目没有说范围,很坑,所以,我们需要把半径开成double型

从左端点开始我们需要找的就是既能覆盖的该点,且与草坪交汇的右边界最远处,这样的一个水管范围。然后再去找下一个水管,直到水管可以覆盖到草坪的右边界结束。

完整代码如下:

#include<stdio.h>
#include<math.h>
#include<algorithm>
using namespace std;
struct node
{
    double a,b;
}s[100020];
bool cmp(node x,node y)
{
    if(x.a==y.a)
        return x.b>y.b;
    return x.a<y.a;
}
int main()
{
    int n;
    double l,w;
    double o,r;
    while(~scanf("%d%lf%lf",&n,&l,&w))
    {
        double q=w/2.0;
        int k=0;
        for(int i=0;i<n;i++)
        {
            scanf("%lf%lf",&o,&r);
            if(r*2<=w) continue;
            s[k].a=o-sqrt(r*r-q*q);
            s[k++].b=o+sqrt(r*r-q*q);
        }
        sort(s,s+k,cmp);
        if(s[0].a>0||k==0)
        {
            printf("-1\n");
            continue;
        }
        double x=0,y=s[0].b;// x 下标为i的水管左边需要覆盖的点,y这个水管右边能覆盖的最大点
        int sum=1;
        for(int i=1;i<k;i++)
        {
            if(s[i].a<=x)
            {
                if(s[i].b>y)
                    y=s[i].b;
                continue;
            }
            if(y>=l) break;
            if(s[i].b<=y) continue;
            if(s[i].a>x)
            {
                if(s[i].a>y) break;
                x=y;
                y=s[i].b;sum++;
            }
        }
        if(y>=l) printf("%d\n",sum);
        else printf("-1\n");
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值