11.01T3 实数二分

3808 -- 【模拟试题】穿越七色虹

Description

  探险队员们跟随两位护法来到了七色虹前。七色虹,就是平面直角坐标系中赤橙黄绿青蓝紫七个半圆,第 i座(1<=i<=7)半圆形彩虹的圆心是(xi,0),半径是ri,半圆上所有点的纵坐标均为非负数。探险队员可以看做一条竖直的、长度等于身高的线段,线段的底端纵坐标为0,最高的一位探险队员的身高为h。
        
  现在探险队员们要从(0,0)穿越七色虹到达(x0,0),穿越七色虹的过程中,探险队员的整个身体必须始终在至少一个半圆形彩虹的内部。由于彩虹的半径 ri 可能太小了,不足以满足这个条件,因此两位护法决定帮助他们把所有彩虹的半径都增大一个非负实数 r。探险队员们想知道,r最小是多少呢?

Input

  第一行两个实数h、x0,表示身高和目的地横坐标。 
  接下来七行每行两个实数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。
 
 
简单的二分
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

posted @ 2018-11-02 15:40  saionjisekai  阅读(245)  评论(0编辑  收藏  举报