11.01T3 实数二分
3808 -- 【模拟试题】穿越七色虹
Description
探险队员们跟随两位护法来到了七色虹前。七色虹,就是平面直角坐标系中赤橙黄绿青蓝紫七个半圆,第 i座(1<=i<=7)半圆形彩虹的圆心是(xi,0),半径是ri,半圆上所有点的纵坐标均为非负数。探险队员可以看做一条竖直的、长度等于身高的线段,线段的底端纵坐标为0,最高的一位探险队员的身高为h。
现在探险队员们要从(0,0)穿越七色虹到达(x0,0),穿越七色虹的过程中,探险队员的整个身体必须始终在至少一个半圆形彩虹的内部。由于彩虹的半径 ri 可能太小了,不足以满足这个条件,因此两位护法决定帮助他们把所有彩虹的半径都增大一个非负实数 r。探险队员们想知道,r最小是多少呢?
现在探险队员们要从(0,0)穿越七色虹到达(x0,0),穿越七色虹的过程中,探险队员的整个身体必须始终在至少一个半圆形彩虹的内部。由于彩虹的半径 ri 可能太小了,不足以满足这个条件,因此两位护法决定帮助他们把所有彩虹的半径都增大一个非负实数 r。探险队员们想知道,r最小是多少呢?
Input
第一行两个实数h、x0,表示身高和目的地横坐标。
接下来七行每行两个实数xi、ri,表示七座半圆形彩虹的圆心和半径。
接下来七行每行两个实数xi、ri,表示七座半圆形彩虹的圆心和半径。
Output
输出最小的r,四舍五入保留 2 位小数。
Sample Input
catclimb.in
4.0 36.0
0.0 4.0
6.0 4.0
12.0 4.0
18.0 4.0
24.0 4.0
30.0 4.0
36.0 4.0
Sample Output
catclimb.out
1.00
Hint
【数据范围】
对于100%的数据,满足0<=xi,x0<=10000,0<h<100。
对于100%的数据,满足0<=xi,x0<=10000,0<h<100。
简单的二分
code:
1 #include<iostream> 2 #include<cstdio> 3 #include<cmath> 4 #include<algorithm> 5 #include<iomanip> 6 using namespace std; 7 const double eps=1e-6; 8 double l[8],r[8],x[8]; 9 double getdis(double a,double b) { 10 return sqrt(a*a-b*b); 11 } 12 double h,x0; 13 struct node{ 14 double l,r; 15 }e[10]; 16 bool cmp(const node&a,const node&b){ 17 return a.l<b.l; 18 } 19 bool check(double mid) { 20 for(int i=1; i<=7; i++) { 21 if(r[i]+mid<h)e[i].l=e[i].r=-1; 22 else{ 23 e[i].l=x[i]-getdis(r[i]+mid,h); 24 e[i].r=x[i]+getdis(r[i]+mid,h); 25 } 26 } 27 sort(e+1,e+8,cmp); 28 double now=0; 29 for(int i=1;i<=7;i++)if(e[i].l<=now&&now<=e[i].r)now=max(now,e[i].r); 30 return now>=x0; 31 } 32 int main() { 33 cin>>h>>x0; 34 for(int i=1; i<=7; i++) { 35 cin>>x[i]>>r[i]; 36 } 37 double l=0,r=9999999.0; 38 while(r-l>=eps) { 39 double mid=(l+r)/2; 40 if(check(mid))r=mid; 41 else l=mid; 42 } 43 cout<<fixed<<setprecision(2)<<l; 44 return 0; 45 }
over