「一本通 1.1 例 3」喷水装置
解题思路
这题看似是圆的覆盖问题,其实我们可以转换成圆的左坐标和右坐标,转换成矩形覆盖问题。
贪心策略:
按左端点从小到大排序,每次遍历一遍,找到符合当前既能覆盖左端点的,又能离右端点的最远的点。
#include <bits/stdc++.h>
#define _for(i,a,n) for(int i=a;i<n;++i)
#define rep(i,a,n)for(int i=a;i<=n;++i)
#define input() int T;cin>>T;while(T--)
#define close() ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
typedef long long ll;
template<class T>inline void read(T &x){bool Finish_read=0;x=0;int f=1;char ch=getchar();while(!isdigit(ch)){if(ch=='-')f=-1;if(ch==EOF)return;ch=getchar();}while(isdigit(ch))x=x*10+ch-'0',ch=getchar();x*=f;Finish_read=1;}
template<class T>inline void print(T x){if(x/10!=0)print(x/10);putchar(x%10+'0');}
template<class T>inline void writeln(T x){if(x<0)putchar('-');x=abs(x);print(x);putchar('\n');}
template<class T>inline void write(T x){if(x<0)putchar('-');x=abs(x);print(x);}
using namespace std;
const int maxn = 15000;
struct node {
double l, r;
inline bool operator < (const node &b) const {
return l < b.l;
}
}arr[maxn + 5];
int main()
{
int T;
double n, x, r, L, W;
read(T);
while(T--) {
read(n), read(L), read(W);
int tot = 0;
_for(i, 0 , n) {
read(x), read(r);
if(r * 2 <= W) continue;
arr[++tot].l = x - sqrt(r * r - W * W / 4.0);
arr[tot].r = x + sqrt(r * r - W * W / 4.0);
}
sort(arr + 1, arr + tot + 1);
double st = 0;
int ans = 0;
while(st < L) {
ans++;
double tmp = st;
for(int id = 1; arr[id].l <= tmp && id <= tot; ++id)
st = max(st, arr[id].r);
if(st == tmp && st < L) {
ans = -1;
break;
}
}
cout << ans << endl;
}
return 0;
}