nyoj_12 喷水装置(二)

喷水装置(二)

时间限制: 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
#include
#include
struct Node
{
	double s,e;
}node[10005];
int cmp(const void* a,const void* b)
{
	return (*(Node*)a).s>(*(Node*)b).s?1:-1;
}
int main()
{
	int N;
	scanf("%d",&N);
	while(N--)
	{
		int n,w,h;
		scanf("%d%d%d",&n,&w,&h);
		for(int i=0;i=w||node[i].e<=0)//左交点大于终点的,以及右交点小于起点的直接舍弃
			{
				i--;
				n--;
				continue;
			}
		}
		qsort(node,n,sizeof(Node),cmp);
		double maxe=0;
		double last=0;
		int i;
		int sum=0;
		int ok=0;
		while(1)
		{
			maxe=0;
			ok=0;//标记此次遍历或搜索是否找到满足条件的喷水装置,如果没找到,则直接结束搜索输出0
			for(i=0;ilast)
					{
						if(!ok)
							sum++;
						ok=1;
						if(node[i].e>maxe)
							maxe=node[i].e;
					}
				}
				else if(ok)
				{
					last=maxe;
					break;
				}
			}
			if(ok)
				last=maxe;
			else
				break;
			if(last>=w)
				break;
		}
		if(ok)
			printf("%d\n",sum);
		else
			printf("0\n");
	}
	return 0;
}


你可能感兴趣的:(贪心算法)