现在的位置: 首页 > 综合 > 正文

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

2018年01月15日 ⁄ 综合 ⁄ 共 1229字 ⁄ 字号 评论关闭

【题目大意】

|         |

|         |

|         |___________

|________________

有像上面这样一个直角拐角(一个口宽为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;
}

抱歉!评论已关闭.