UVA10382 Watering Grass


题目描述

\(L\) 米,宽 \(W\) 米的草坪里装有 \(n\) 个浇灌喷头。每个喷头都装在草坪中心线上(离两边各 \(\dfrac W 2\) 米)。我们知道每个喷头的位置(离草坪中心线左端的距离,即圆心坐标 \(x\)),以及它能覆盖到的浇灌范围,即半径 \(r\)

请问:如果要同时浇灌整块草坪,最少需要打开多少个喷头?如果无解请输出 \(-1\)

大体思路

代码

#include 
using namespace std;
#define rep(ii,aa,bb) for(re int ii = aa; ii <= bb; ii++)
#define Rep(ii,aa,bb) for(re int ii = aa; ii >= bb; ii--)
typedef long long ll;
typedef unsigned long long ull;
typedef double db;
typedef pair PII;
const int maxn = 2e4 + 5;
const db eps = 1e-8;
namespace IO_ReadWrite {
	#define re register
	#define gg (p1 == p2 && (p2 = (p1 = _buf) + fread(_buf, 1, 1<<21, stdin), p1 == p2) ? EOF :*p1++)
	char _buf[1<<21], *p1 = _buf, *p2 = _buf;
	template 
	inline void read(T &x){
		x = 0; re T f=1; re char c = gg;
		while(c > 57 || c < 48){if(c == '-') f = -1;c = gg;}
		while(c >= 48 &&c <= 57){x = (x<<1) + (x<<3) + (c^48);c = gg;}
		x *= f;return;
	}
	inline void ReadChar(char &c){
		c = gg;
		while(!isalpha(c)) c = gg;
	}
	template 
	inline void write(T x){
		if(x < 0) putchar('-'), x = -x;
		if(x > 9) write(x/10);
		putchar('0' + x % 10);
	}
	template 
	inline void writeln(T x){write(x); putchar('\n');}
}
using namespace IO_ReadWrite;
ll n, tot;
db L, W;
struct Segment{ 
	db l, r;
	bool operator <(const Segment &x)const{
		return l < x.l;
	}
} a[maxn];
int main () {
//	int T; scanf("%d", &T);
	while(cin >> n >> L >> W) {
		tot = 0;
		rep(i, 1, n) {
			db x, r;
			cin >> x >> r;
			if(r * 2 <= W) continue;
			db _l = x - sqrt(r * r * 1.0 - W * W * 1.0 / 4.0);
			db _r = x + sqrt(r * r * 1.0 - W * W * 1.0 / 4.0);;
			a[++tot] = {_l, _r};
		}
		sort(a + 1, a + tot + 1);
		int ans = 0, i = 0; 
		db s = 0, ed = L * 1.0;
		while(s < L) {
			db mx = s;
			while(i < tot && a[i + 1].l <= s) {
				i ++;
				mx = max(mx, a[i].r);
			}
			ans ++;
			if(mx <= s && mx < ed) {
				ans = -1;
				break;
			}
			s = mx;
		}
		writeln(ans);
	}
	
	return 0;
}