Codeforces Problemset 98C(#78 div.1 C)

【题目大意】

|         |

|         |

|         |___________

|________________

有像上面这样一个直角拐角(一个口宽为a,一个口宽为b),两边走廊可以认为是无限长。

问一个表面光滑的长为l的矩形宽w(宽当然比长小了)最大是多少。

【输入】

一行三个整数,a、b、l

【输出】

一个实数w,要求误差不超过10^-7


1A……两道作业题我都是1A,不科学啊……明明很没信心的


我们来考虑一下这个矩形滑过去的过程,来分几种情况讨论一下

讨论的时候为了方便令a<=b


1、l<=a

这种情况w<=l<=a,怎么他都不会卡住啊!所以令w=l


2、a<=l<=b

这种情况如果a<=w<=l<=b

那么……

他掉不到拐角处,入口处就被卡着了……

令w=a

可以直接推到拐角处,然后再从另外一边推出来

这时候答案w=a


3、b<=l

这是最一般的情况。

设f(x)表示宽为x的矩形是否能够通过,显然这个函数具有单调性。

问题就转化到如何实现函数f(x)。

可以把转弯的过程看作l这条边贴着墙壁先降到最底层,然后靠着墙慢慢转过来。

这个时候距离那个很尖锐的点的距离(如果穿过墙了我们认为距离是负的)关于l那条边跟外侧某条边的墙的夹角x是个单峰函数。

三分即可求出峰值。具体怎么做就不赘述了。


#include <cstdio>
#include <iostream>
#include <cmath>
using namespace std;
int a,b,l;
double s,e,mid;

double quick(double x,double w)
{
       double o,p,q;
       if (x<1e-8) o=1,p=0,q=0;
       else
       if (x>asin(1)-1e-8) o=0,p=1,q=0;
       else                o=-tan(x),p=-1,q=l*sin(x)+w/cos(x);
       return -(o*a+p*b+q)/sqrt(o*o+p*p);
}

double calc(double w)
{
       double x,y,s,e;
       s=0;
       e=asin(1);
       while (e-s>1e-8)
       {
             x=s+(e-s)/3;
             y=e-(e-s)/3;
             if (quick(x,w)<quick(y,w)) e=y;
             else                   s=x;
       }
       return quick(s,w);
}

int main()
{
    cin >> a >> b >> l;
    if (a>b) swap(a,b);
    if (l<=a) printf("%.7f",(double)l);
    else
    if (l<=b) printf("%.7f",(double)a);
    else
    {
        s=0;
        e=a;
        while ((e-s)>1e-8)
        {
              mid=(s+e)/2;
              if (calc(mid)<1e-8) e=mid;
              else                s=mid;
        }
        if (calc(s)<1e-8) printf("My poor head =(");
        else              printf("%.7f",s);
    }
    cout << endl;
    cin.get();
    cin.get();
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值