#10002. 「一本通 1.1 例 3」喷水装置
内存限制:512 MiB时间限制:1000 ms标准输入输出
题目类型:传统评测方式:文本比较
上传者: 1bentong
题目描述
长 LLL 米,宽 WWW 米的草坪里装有 nnn 个浇灌喷头。每个喷头都装在草坪中心线上(离两边各 W2\frac{W}{2}2W 米)。我们知道每个喷头的位置(离草坪中心线左端的距离),以及它能覆盖到的浇灌范围。
请问:如果要同时浇灌整块草坪,最少需要打开多少个喷头?
输入格式
输入包含若干组测试数据。
第一行一个整数 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;
}