UVA - 10382 Watering Grass (区间覆盖) (贪心) (day_6_J)

本文探讨了如何计算最少数量的喷头以确保长条形草丛完全被水覆盖的问题。通过将区域覆盖转化为区间覆盖,文章提出了一种算法,该算法首先筛选出有效喷头,然后按其左侧边界排序,最后选择能够覆盖最远距离的喷头,直至整个区域被覆盖。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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

题目简述:

一长方形草丛,长l,宽w,给出n个喷头的位置x和喷洒半径r,问最少需要开几个能给整个草丛都浇上水。

题目分析:

将区域覆盖转为区间覆盖,有些半径不到宽一半大的喷头可以直接忽略。然后将喷头按照他所能覆盖的最左的边界升序排序。然后在左边界小于这个喷头的喷头中选取右边界最大的喷头作为下一个喷头,直至覆盖整个草丛。

代码实现:

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<string>
#include<vector>
#include<stack>
#include<cstdlib>
#include<cmath>
#include<queue>
//#include <bits/stdc++.h>
using namespace std;

const int INF = 0x3f3f3f3f;
#define pf          printf
#define sf(n)       scanf("%d", &n)
#define sff(a,b)    scanf("%d %d", &a, &b)
#define sfff(a,b,c) scanf("%d %d %d", &a, &b, &c)
#define ms(i,j) memset(i,j,sizeof(i))

struct point
{
    double l,r;
    bool operator< (const point b)const
    {
        return l<b.l;
    }
} a[10005];
int main()
{
    int n,l,w,x,i,j,rt;
    while(~sfff(n,l,w))
    {
        int sum=0,k=0;
        for(int i=0; i<n; i++)
        {
            sff(x,rt);
            if(rt>((double)w)/2)
            {
                a[k].l=x-sqrt((double)rt*rt-((double)w)*((double)w)/4);
                a[k++].r=x+sqrt((double)rt*rt-((double)w)*((double)w)/4);
            }
        }
        sort(a,a+k);
        double r=0;
        for(i=0; i<k; i=j)
        {
            if(a[i].l>r)
                break;
            for(j=i+1; j<k&&a[j].l<=r; j++)
            {
                if(a[j].r>a[i].r)
                    i=j;
            }
            sum++;
            r=a[i].r;
            if(r>=l)
                break;
        }
        if(r>=l)
            pf("%d\n",sum);
        else
            pf("-1\n");
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值