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
以爲是個dp,原來是個貪心,維護一個相對於當前位置能夠向右覆蓋的最大距離,依次更新即可

#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
const int maxn = 1e5+10;
struct node{
	double s, e;
}rec[maxn];
bool cmp(const node& a, const node& b){
	return a.s < b.s;
}
int main(){
	int t, n, v, ans;
	double w, h, cur;
	scanf("%d", &t);
	while(t--){
		scanf("%d%lf%lf", &n, &w, &h);
		h /= 2;
		cur = v = ans = 0;
		for(int i = 0; i < n; i++){
			double a, b;
			scanf("%lf%lf", &a, &b);
			if(b <= h) continue;
			rec[v].s = a-sqrt(b*b-h*h);
			rec[v++].e = a+sqrt(b*b-h*h);
		}
		sort(rec, rec+v, cmp);
		bool flag = false;
		while(cur < w){
			double Max = 0;
			for(int i = 0; i < v && rec[i].s <= cur; i++){//cur是當前位置,Max是最大的相對向右覆蓋距離
				if(Max < rec[i].e - cur) Max = rec[i].e - cur;
			}
			if(Max == 0){//若覆蓋不到最右端,肯定會有無法更新的時候,即Max爲0,可以作爲終止條件
				flag = true;
				break;
			}
			cur += Max;
			ans++;
		}
		printf("%d\n", flag ? 0 : ans);
	}
	return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章