[NOIP 模拟]穿越七色虹 二分答案

来源:互联网 发布:知乎app怎么关注话题 编辑:程序博客网 时间:2024/04/27 21:57

题目

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

题解

二分答案,勾股定理求线段,排序线段,判断区间是否全覆盖

代码

#include <cstdio>#include <iostream>#include <cstring>#include <algorithm>#include <cmath>using namespace std;double h,x0,l,r,ans;struct Holder{    double x,y;}b[10005];struct Complex{    double ex,er;}e[10005];int cmp(Holder z,Holder k) {    return z.x<k.x;}int cmp2(Complex z, Complex k){    return z.ex<k.ex;}double Calculate(int i, double x) {    return sqrt((e[i].er+x)*(e[i].er+x)-h*h);}int Judge(double x) {    for(int i=1;i<=7;i++){        if(x+e[i].er>=h){            double y=Calculate(i,x);            b[i].x=e[i].ex-y;            b[i].y=e[i].ex+y;        }    }       double cmax=b[1].y,cmin=b[1].x;    for(int i=2;i<=7;i++){        if(b[i].x<=cmax){            if(b[i].x<cmin){                cmin=b[i].x;            }            if(b[i].y>cmax){                cmax=b[i].y;            }        }    }    if(cmin<=0&&cmax>=x0){        return 1;    }else{        return 0;    }}double Bisection() {    l=0;r=x0;double mid;    while(r-l>=0.001){        mid=(l+r)/2.0;        if(Judge(mid)) r=mid;        else l=mid;    }    return mid;}int main() {    cin>>h>>x0;    for(int i=1;i<=7;i++) {        cin>>e[i].ex>>e[i].er;    }    sort(e+1,e+1+7,cmp2);    ans=Bisection();    printf("%.2lf",ans);}
0 0