【LOJ10002】#10002. 「一本通 1.1 例 3」喷水装置(贪心)

题目链接

#10002. 「一本通 1.1 例 3」喷水装置

内存限制:512 MiB时间限制:1000 ms标准输入输出

题目类型:传统评测方式:文本比较

上传者: 1bentong

提交提交记录统计讨论

1

测试数据

题目描述

长 LLL 米,宽 WWW 米的草坪里装有 nnn 个浇灌喷头。每个喷头都装在草坪中心线上(离两边各 W2\frac{W}{2}​2​​W​​ 米)。我们知道每个喷头的位置(离草坪中心线左端的距离),以及它能覆盖到的浇灌范围。

请问:如果要同时浇灌整块草坪,最少需要打开多少个喷头?

Picture1

输入格式

输入包含若干组测试数据。

第一行一个整数 TTT 表示数据组数;

每组数据的第一行是整数 nnn、LLL 和 WWW;

接下来的 nnn 行,每行包含两个整数,给出一个喷头的位置和浇灌半径(上面的示意图是样例输入第一组数据所描述的情况)。

输出格式

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

样例

样例输入

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

样例输出

6
2
-1

数据范围与提示

对于 100%100\%100% 的数据,n≤15000n \le 15000n≤15000

【解题思路】

先将不符合条件的区间去掉(即半径小于W,不然宽度无法符合),将符合条件的按区间存入节点中。区间的左边界是x*1.0-sqrt(r*r-W*W/4.0),要计算x轴的最小长度,而不是x-r。然后将区间按照左边界从小到大排序,依次找到能够覆盖L点的最大右端点。

【代码】

#include<bits/stdc++.h>
using namespace std;
const int maxn=2e4+5;
struct Node
{
    double l,r;
}node[maxn];
bool cmp(Node a,Node b)
{
    return a.l<b.l;
}
int main()
{
    int n,L,W,T;
    scanf("%d",&T);
    while(T--)
    {
        int x,r,cnt=0;
        scanf("%d%d%d",&n,&L,&W);
        while(n--)
        {
            scanf("%d%d",&x,&r);
            if(r>=W)
            {
                node[cnt].l=x*1.0-sqrt(r*r-W*W/4.0);
                node[cnt++].r=x*1.0+sqrt(r*r-W*W/4.0);
            }
        }
        sort(node,node+cnt,cmp);
        int flag=0,ans=0,i=0;
        double t=0;
        while(t<L)
        {
            ans++;
            double s=t;
            while(node[i].l<=s && i<cnt)
            {
                if(t<node[i].r)t=node[i].r;
                i++;
            }
            if(s==t && s<L)
            {
                flag=1;
                break;
            }
        }
        if(flag)printf("-1\n");
        else printf("%d\n",ans);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_39826163/article/details/82806191
今日推荐