bzoj4885: [Lydsy2017年5月月赛]长方体

传送门
好题(蛋疼题
《出题人各种被*系列》

《论如何快速找*》

首先长方体每个顶点等价,不用算8个。
其次一个点最远的距离显然是在3个与其不相邻的面取到的。
然后我们大力枚举3个面,大力来一发三分套三分。
接下来的问题是,如何求出长方体上两个顶点之间最短路的距离。
1.展开图如下:
这种情况十分简单,自己yy一下就可以了。
2.展开图如下
这里写图片描述
这也也是可以用勾股定理算出来的。
到此,全部情况讨论完毕,得到答案。
只不过我脑细胞耗费太多了
~~*掉辣鸡出题人~~

#include<cmath>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#define db double
#define EPS 1e-8
using namespace std;
db L,W,H,ans;
db sqr(db x){return x*x;}
db calc(db a,db b,db c){
    db ans=1e20;
    if (c!=H) ans=min(ans,(a+b)*(a+b)+c*c);
        else ans=min(ans,min(sqr(L+b)+sqr(H+L-a),sqr(W+a)+sqr(H+W-b)));
    if (b!=W) ans=min(ans,(a+c)*(a+c)+b*b);
        else ans=min(ans,min(sqr(H+a)+sqr(W+H-c),sqr(L+c)+sqr(W+L-a)));
    if (a!=L) ans=min(ans,(b+c)*(b+c)+a*a);
        else ans=min(ans,min(sqr(W+c)+sqr(L+W-b),sqr(H+b)+sqr(L+H-c)));
    return ans;
}
db solvexy(db a,db b,db c){
    db l=0,r=c,m1,m2,v1,v2,ans=0;
    while (r-l>EPS){
        m1=(l*2+r)/3;
        m2=(l+2*r)/3;
        v1=calc(a,b,m1);
        v2=calc(a,b,m2);
        ans=max(ans,max(v1,v2));
        if (v1>v2) r=m2; else l=m1;
    }
    return ans;
}
db solvexz(db a,db b,db c){
    db l=0,r=b,m1,m2,v1,v2,ans=0;
    while (r-l>EPS){
        m1=(l*2+r)/3;
        m2=(l+2*r)/3;
        v1=calc(a,m1,c);
        v2=calc(a,m2,c);
        ans=max(ans,max(v1,v2));
        if (v1>v2) r=m2; else l=m1;
    }
    return ans;
}
db solvex(db a,db b,db c){
    db l=0,r=b,m1,m2,v1,v2,ans=0;
    while (r-l>EPS){
        m1=(l*2+r)/3;
        m2=(l+2*r)/3;
        v1=solvexy(a,m1,c);
        v2=solvexy(a,m2,c);
        ans=max(ans,max(v1,v2));
        if (v1>v2) r=m2; else l=m1;
    }
    return ans;
}
db solvey(db a,db b,db c){
    db l=0,r=a,m1,m2,v1,v2,ans=0;
    while (r-l>EPS){
        m1=(l*2+r)/3;
        m2=(l+2*r)/3;
        v1=solvexy(m1,b,c);
        v2=solvexy(m2,b,c);
        ans=max(ans,max(v1,v2));
        if (v1>v2) r=m2; else l=m1;
    }
    return ans;
}
db solvez(db a,db b,db c){
    db l=0,r=a,m1,m2,v1,v2,ans=0;
    while (r-l>EPS){
        m1=(l*2+r)/3;
        m2=(l+2*r)/3;
        v1=solvexz(m1,b,c);
        v2=solvexz(m2,b,c);
        ans=max(ans,max(v1,v2));
        if (v1>v2) r=m2; else l=m1;
    }
    return ans;
}
int main(){
    scanf("%lf%lf%lf",&L,&W,&H);
    ans=min((L+W)*(L+W)+H*H,min((L+H)*(L+H)+W*W,(W+H)*(W+H)+L*L));
    ans=max(ans,solvex(L,W,H));
    ans=max(ans,solvey(L,W,H));
    ans=max(ans,solvez(L,W,H));
    printf("%.15lf\n",sqrt(ans));
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值