NYOJ:噴水裝置(二)(貪心)
阿新 • • 發佈:2018-11-26
http://acm.nyist.edu.cn/JudgeOnline/problem.php?pid=12
描述
有一塊草坪,橫向長w,縱向長為h,在它的橫向中心線上不同位置處裝有n(n<=10000)個點狀的噴水裝置,每個噴水裝置i噴水的效果是讓以它為中心半徑為Ri的圓都被潤溼。請在給出的噴水裝置中選擇儘量少的噴水裝置,把整個草坪全部潤溼。
輸入
第一行輸入一個正整數N表示共有n次測試資料。
每一組測試資料的第一行有三個整數n,w,h,n表示共有n個噴水裝置,w表示草坪的橫向長度,h表示草坪的縱向長度。
隨後的n行,都有兩個整數xi和ri,xi表示第i個噴水裝置的的橫座標(最左邊為0),ri表示該噴水裝置能覆蓋的圓的半徑。
輸出
每組測試資料輸出一個正整數,表示共需要多少個噴水裝置,每個輸出單獨佔一行。
如果不存在一種能夠把整個草坪溼潤的方案,請輸出0。
樣例輸入
2 2 8 6 1 1 4 5 2 10 6 4 5 6 5
樣例輸出
1 2
貪心問題,先按照橫座標排序
在選取噴水裝置的時候,可以從第一個開始,找到可以把從a[i].x到盡頭都溼潤的一個,
這時可以把盡頭更新到未溼潤區域,再從第一個開始到上一步找到的那個。
如果找完都不滿足條件,就無法把整個草坪都溼潤。
#include<stdio.h> #include<math.h> #include<algorithm> #define N 100200 using namespace std; struct data { int x; int r; }a[N]; int cmp(struct data x1,struct data x2) { return x1.x<x2.x; } int main() { int t,i,n,ans,w,h; double m; scanf("%d",&t); while(t--) { ans=0; scanf("%d%d%d",&n,&w,&h); for(i=0;i<n;i++) scanf("%d%d",&a[i].x,&a[i].r); sort(a,a+n,cmp); m=w; for(i=0;i<n;i++) { if(m<=0) break; if(double( ( m - a[i].x ) * ( m - a[i].x ) +( h / 2.0 ) * ( h / 2.0 ) )<=(a[i].r * a[i].r)) { m=a[i].x-(sqrt( double((a[i].r * a[i].r )-( h / 2.0 ) * ( h / 2.0 ))) ); ans++; n=i; i=-1; } } if(m<=0) printf("%d\n",ans); else printf("0\n"); } return 0; }