1. 程式人生 > >南陽OJ-12-噴水裝置(二)貪心+區間覆蓋

南陽OJ-12-噴水裝置(二)貪心+區間覆蓋

gpo algo pro 直接 stream () spa 則無 end

題目鏈接:

http://acm.nyist.edu.cn/JudgeOnline/problem.php?pid=12

題目大意:

有一塊草坪,橫向長w,縱向長為h,在它的橫向中心線上不同位置處裝有n(n<=10000)個點狀的噴水裝置,每個噴水裝置i噴水的效果是讓以它為中心半徑為Ri的圓都被潤濕。請在給出的噴水裝置中選擇盡量少的噴水裝置,把整個草坪全部潤濕。

傳送門:噴水裝置(一)

思路:

區間覆蓋問題,每個點有一段噴水區間,按照左端點排序即可,設置兩變量begin, end,依次掃過去,每次取覆蓋begin的區間更新end,如果沒能覆蓋begin,說明已經到了當前的最右端,begin=end,再次掃描,如果每次掃描開始的時候就不能覆蓋begin,則無解,如果每次掃描的時候沒有找到合適的end,也無解。如果最終的begin<l也表示到達不了終點。

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 #include<cmath>
 6 using namespace std;
 7 const int maxn = 1e4 + 10;
 8 int T, n;double l, w;
 9 struct node
10 {
11     double x, y;
12     bool operator < (const node a)const
13
{ 14 return x < a.x; 15 } 16 node(){} 17 node(double x, double y):x(x), y(y){} 18 }; 19 node a[maxn]; 20 int main() 21 { 22 cin >> T; 23 while(T--) 24 { 25 cin >> n >> l >> w; 26 w = w * 0.5; 27 int tot = 0; 28 double
x, r; 29 for(int i = 0; i < n; i++) 30 { 31 cin >> x >> r; 32 if(r <= w)continue; 33 double c = sqrt(1.0 * r * r - w * w); 34 a[tot].x = 1.0 * x - c; 35 a[tot++].y = 1.0 * x + c; 36 if(a[tot - 1].x > l || a[tot - 1].y < 0)tot--; 37 } 38 sort(a, a + tot); 39 double begin = 0, end = -1; 40 int ans = 0; 41 for(int i = 0; i < tot && begin < l;) 42 { 43 if(a[i].x > begin) 44 { 45 ans = 0; 46 break; 47 } 48 while(i < tot && a[i].x <= begin)//覆蓋begin的區間更新出最大的end 49 { 50 end = max(end, a[i].y); 51 i++; 52 } 53 if(end < 0)//說明沒有找到合適的區間,直接無解 54 { 55 ans = 0; 56 break; 57 } 58 ans++; 59 begin = end;//更新兩者 60 end = -1; 61 } 62 if(begin < l)ans = 0; 63 cout<<ans<<endl; 64 } 65 return 0; 66 }

南陽OJ-12-噴水裝置(二)貪心+區間覆蓋