喷水装置
题目描述:
长 L 米,宽 w
米的草坪里装有 n 个浇灌喷头。每个喷头都装在草坪中心线上(离两边各 w/2 米)。我们知道每个喷头的位置(离草坪中心线左端的距离),以及它能覆盖到的浇灌范围。
请问:如果要同时浇灌整块草坪,最少需要打开多少个喷头?
输入格式:
输入包含若干组测试数据。
第一行一个整数 t 表示数据组数;
每组数据的第一行是整数 n、L 和w ;
接下来的 n 行,每行包含两个整数,给出一个喷头的位置和浇灌半径
输出格式:
对每组测试数据输出一个数字,表示要浇灌整块草坪所需喷头数目的最小值。如果所有喷头都打开也不能浇灌整块草坪,则输出 -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%的数据n<=15000
此题目本身并不难,但是请记得开double(包括宽度,别问我怎么知道的)
关键步骤:求出圆覆盖到的矩形的上边或下边,储存后用sort按覆盖到的右端距离进行从小到大的排序。而且由于本题有多组数据,需注意结构体和诸多变量的清零。选择时以自己的最右端为界限,所选下一个必须覆盖到此端点并尽可能的右端点大(贪心),直到没有再能覆盖它(输出-1)或右端点大于矩形长度(ans)
#include<bits/stdc++.h>
using namespace std;
int t,n,l,ans=0;
int aa,b,xx;
double k2,w;//w也得是double!后面w/2有可能是小数
struct node{
double x,y;//double
}a[16000];
bool cmp(node a,node b){
return a.x<b.x;
}
bool flag=1;
int main(){
cin>>t;
while(t--){
ans=0;
flag=1;
memset(a,0,sizeof(a));//清零!!!!!
cin>>n>>l>>w;
xx=0;
for(int i=1;i<=n;i++){
cin>>aa>>b;
if(b>w/2){//若半径小于w/2,则圆在矩形内,无法覆盖,直接跳过
xx++;
a[xx].x=aa-sqrt(b*b-(w/2*w/2));//圆覆盖到矩形上的左端点
a[xx].y=aa+sqrt(b*b-(w/2*w/2));//圆覆盖到矩形上的右端点
}
}
k2=0;
sort(a+1,a+1+xx,cmp);
while(k2<l){
double k3=k2;
ans++;//每次循环都只会最终找到一个,因此每次循环ans++
for(int i=1;i<=xx&&a[i].x<=k3;i++){
if(a[i].y>=k2){
k2=a[i].y;//找到最大点
}
}
if(k3==k2&&k3<l){//若没有找到下一个点且此时没有覆盖到矩形右端
cout<<"-1"<<endl;//则无法全覆盖,直接cout<<-1
flag=0;
break;
}
}
if(flag)
cout<<ans<<endl;
}
return 0;
}