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

喷水装置
题目描述:

长 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;
} 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值