【NOIP2013模拟】穿越七色虹


【NOIP2013模拟】穿越七色虹

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
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
1.00

Data Constraint
对于100%的数据,满足 0<=xi,x0<=10000;0< h<=100。


解题思路

二分答案,判断答案是否符合条件:
利用勾股定理判断线段是否覆盖(0,0)到(x0,0),注意精度,有可能有点超过x0的情况
Codes:

var a,b:array[0..7,1..2]of real;
    i,j,tot:longint;
    h,x0,l,r,m,ans:real;
function f(a,b:real):real;
begin
    exit(sqrt(a*a-b*b));
end;
function pan:boolean;
    var i,j,l:longint;
        bool:boolean;
begin
    if tot=0 then exit(false);
    if b[1,1]>0 then exit(false);  //判断是否覆盖前端
    bool:=true;
    for i:=tot downto 1 do
        if b[i,2]>=x0 then
        begin
            bool:=false;
            break;
        end;
    if bool then exit(false);  //判断是否覆盖后端
    l:=1;
    for i:=1 to tot do
    begin
        if i>l then exit(false);
        for j:=i+1 to tot do
            if b[i,2]>=b[j,1] then
            begin
                if j>l then l:=j;
                if l=tot then exit(true);  //判断彩虹所覆盖范围是否依次相连
            end;
    end;
    exit(true);
end;
begin
    read(h,x0);
    l:=0; r:=x0; ans:=x0;
    for i:=1 to 7 do read(a[i,1],a[i,2]);
    while l<r do                   //二分答案
    begin
        m:=trunc((l+r)*5000)/10000;
        tot:=0;
        for i:=1 to 7 do
            if a[i,2]+m>=h then   //加入半径增加后超过最高身高的彩虹
            begin
                inc(tot);
                b[tot,1]:=a[i,1]-f(a[i,2]+m,h);
                b[tot,2]:=a[i,1]+f(a[i,2]+m,h);  //存入彩虹所管到的范围
            end;
        for i:=1 to tot-1 do
            for j:=i+1 to tot do
                if b[i,1]>b[j,1] then
                begin
                    b[0]:=b[i];
                    b[i]:=b[j];
                    b[j]:=b[0];
                end;
        for i:=1 to tot do
            if b[i,1]>x0 then break;
        tot:=i-1;   //将彩虹所管范围超过(0,0)到(x0,0)的排除
        if pan then
        begin
            r:=m-0.001;
            ans:=m;
        end else
            l:=m+0.001;
    end;
    writeln(ans:0:2);
end.
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值