「一本通 1.1 例 3」噴水裝置
阿新 • • 發佈:2018-12-25
題目傳送門
這題看似是圓的覆蓋問題,其實我們可以轉換成圓的左座標和右座標,轉換成矩形覆蓋問題。
貪心策略:
按左端點從小到大排序,每次遍歷一遍,找到符合當前既能覆蓋左端點的,又能離右端點的最遠的點。
#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; }