喷水装置(二)

5 篇文章 0 订阅
喷水装置(二)
时间限制:3000 ms  |  内存限制:65535 KB
难度:4

描述
    有一块草坪,横向长w,纵向长为h,在它的橫向中心线上不同位置处装有n(n<=10000)个点状的喷水装置,每个喷水装置i喷水的效果是让以它为中心半径为Ri的圆都被润湿。请在给出的喷水装置中选择尽量少的喷水装置,把整个草坪全部润湿。

输入
    第一行输入一个正整数N表示共有n次测试数据。
    每一组测试数据的第一行有三个整数n,w,h,n表示共有n个喷水装置,w表示草坪的横向长度,h表示草坪的纵向长度。
    随后的n行,都有两个整数xi和ri,xi表示第i个喷水装置的的横坐标(最左边为0),ri表示该喷水装置能覆盖的圆的半径。
输出
    每组测试数据输出一个正整数,表示共需要多少个喷水装置,每个输出单独占一行。
    如果不存在一种能够把整个草坪湿润的方案,请输出0。
样例输入

    2
    2 8 6
    1 1
    4 5
    2 10 6
    4 5
    6 5

样例输出

    1

    2

题意:》》》

思路:此问题可转化为区间覆盖问题,每个区间的最表可以表示出来,接下来就是贪心算法,先将每个区间的左端点升序来排序,然后选取右端点尽量长的区间,当然要选取的区间的左端点小于上一区间的右端点,直到将整个区间覆盖或者区间选取到最后结束,同时还要注意纵向的草坪要全部覆盖才能将其选为可选取的区间,再有就是精度问题,

下面附上代码:

#include<bits/stdc++.h>
using namespace std;
struct node{
	double a;
	double b;
}s[10005];
double len(double a,double b)
{
	return sqrt(a*a-b*b);
}
bool cmp(node A,node B)
{
	return A.a<B.a;
}
int main()
{
	int N; 
	double n,w,h,x,y;
	scanf("%d",&N);
	while(N--)
	{
		int j=0;
		scanf("%lf %lf %lf",&n,&w,&h);
		for(int i=0;i<n;i++)
		{
			scanf("%lf %lf",&x,&y);
			if(y>h/2.0) 
			{
				double l=len(y*1.0,h/2.0);
				s[j].a=x-l;
				s[j].b=x+l;
				j++;
			}
		}
		sort(s,s+j,cmp);
		double p=0.0;
		int k=0;
		while(p<w)
		{
			double m=0.0;
			for(int i=0;(i<j)&&(s[i].a<=p);i++)
				if((s[i].b-p)>m) m=s[i].b-p;
			if(m!=0)
			{
				k++;
				p+=m;
			}
			else 
				break;
		}
		if(p<w) printf("0\n");
		else printf("%d\n",k);
	}
	
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值