1. 程式人生 > >NYOJ:噴水裝置(二)(貪心)

NYOJ:噴水裝置(二)(貪心)

http://acm.nyist.edu.cn/JudgeOnline/problem.php?pid=12

描述

有一塊草坪,橫向長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

貪心問題,先按照橫座標排序

在選取噴水裝置的時候,可以從第一個開始,找到可以把從a[i].x到盡頭都溼潤的一個,

這時可以把盡頭更新到未溼潤區域,再從第一個開始到上一步找到的那個。

如果找完都不滿足條件,就無法把整個草坪都溼潤。

#include<stdio.h>
#include<math.h>
#include<algorithm>
#define N 100200
using namespace std;
struct data
{
	int x;
	int r;
}a[N];
int cmp(struct data x1,struct data x2)
{
	return x1.x<x2.x;
}
int main()
{
	int t,i,n,ans,w,h;
	double m;
	scanf("%d",&t);
	while(t--)
	{
		ans=0;
		scanf("%d%d%d",&n,&w,&h);
		for(i=0;i<n;i++)
			scanf("%d%d",&a[i].x,&a[i].r);
		sort(a,a+n,cmp);
		m=w;
		for(i=0;i<n;i++)
		{
			if(m<=0)
				break;
			if(double( ( m - a[i].x ) * ( m - a[i].x ) +( h / 2.0 ) * ( h / 2.0 ) )<=(a[i].r * a[i].r))
			{
				m=a[i].x-(sqrt( double((a[i].r * a[i].r )-( h / 2.0 ) * ( h / 2.0 ))) );
				ans++;
				n=i;
				i=-1;
			}
		}
		if(m<=0)
			printf("%d\n",ans);
		else
			printf("0\n"); 
	}
	return 0;
}