1. 程式人生 > 實用技巧 >一本通 1.1 例 3【噴水裝置】

一本通 1.1 例 3【噴水裝置】

題目linkhttps://loj.ac/problem/10002

首先這道題不是用中心點 $+$ 半徑作為一個區間的,可以發現如果那樣算的話,圓與圓之間可能還會有一個縫隙,所以應該用勾股定理求出每一個圓所覆蓋的區間,注意一下上下的距離夠不夠,然後就是區間覆蓋問題,直接貪心即可。$O(n$2$)$

 1 #include <bits/stdc++.h>
 2 #define INF 0x3f3f3f3f
 3 using namespace std;
 4 int T, n, l, w, num;
 5 struct Str {double l, r;}stu[15010];
 6 int cmp(Str a, Str b) {return
a.l == b.l ? a.r > b.r : a.l < b.l;} 7 double cal(int R) {return (double)sqrt(R * R * 1.0 - w * w * 1.0 / 4);} 8 int main() 9 { 10 scanf("%d", &T); 11 while(T--) 12 { 13 num = 0; 14 scanf("%d %d %d", &n, &l, &w); 15 for(int i = 1, x, R; i <= n; ++i)
16 { 17 scanf("%d %d", &x, &R); if(2 * R < w) continue; 18 stu[++num].l = x * 1.0 - cal(R), stu[num].r = x * 1.0 + cal(R); 19 if(stu[num].l < 0) stu[num].l = 0; if(stu[num].r > l) stu[num].r = l; 20 } 21 sort(stu + 1, stu + num + 1
, cmp); if(stu[1].l > 0) {puts("-1"); continue;} 22 double end = 0; int ans = 0; 23 for(int i = 0; ; ++ans) 24 { 25 if(end >= l) break; 26 int change = 0; double maxe = end;//注意這裡maxe是double! 27 for(int j = i + 1; j <= num; ++j) 28 { 29 if(stu[j].l > end) break; 30 if(stu[j].r > maxe) maxe = stu[j].r, i = j, change = 1; 31 } 32 end = maxe; 33 if(!change) break; 34 } 35 if(end < l) puts("-1"); else printf("%d\n", ans); 36 } 37 return 0; 38 }