第六次训练 J题

问题链接:Problem J

问题简述:

有一块草坪长为l,宽为w,同时有n个喷头,给出喷头的位置(距离草坪左端的距离),与喷头喷洒的范围,问喷头的范围能否覆盖整块草坪,若能,输出要开的最少喷头数,若不能,输出-1。

问题分析:

典型的区间覆盖问题。但该问题为二维问题,难度在于如何将二维问题转化为一维问题,从而用简单的一维区间覆盖解决问题。可以发现,喷头可以覆盖到的草坪上下两端的范围可以用勾股定理转换成水平方向的区间,而若能覆盖及上下两端,则水平方向必然也能覆盖到,因此只用将每个喷头可以覆盖到的最远上下两端点转换为覆盖区间,即可求解。求解区间覆盖问题用贪心思想即可,即每次取区间长度最长的区间。

程序说明:

要注意的一个细节是问题设计到的变量尽量都用double表示,防止勾股计算过程中忘记将整型转换为double而导致计算出现错误。

AC通过的C语言程序如下:

#include<iostream>
#include<cstdio>
#include<cstdlib> 
#include<algorithm>
#include<queue>
#include<set>
#include<cstring>
#include<cmath>
using namespace std;
struct node{
	int pos;
	double l,r;
}point[10005];
bool cmp(node a,node b){
	return a.l<b.l;
}
int main(){
	std::ios::sync_with_stdio(false);
	int n,l,w;
	while(cin>>n>>l>>w){
		double r;
		double m=(double)w/2;
		for(int i=0;i<n;i++){
			cin>>point[i].pos>>r;
			double del=sqrt(r*r-m*m);
			point[i].l=point[i].pos-del;
			point[i].r=point[i].pos+del;
		}
		sort(point,point+n,cmp);
		if(point[0].l>0){
			cout<<-1<<endl;
			continue;
		}
		double L=0,R=0;
		int ans=0;
		while(R<l){
			for(int i=0;i<n;i++){
				if(point[i].l<=L&&point[i].r>R){
					R=point[i].r;
				}
			}
			if(R==L){
				ans=-1;
				break;
			}
			L=R;
			ans++;
		}
		cout<<ans<<endl;
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值