码迷,mamicode.com
首页 > 其他好文 > 详细

P2571 [SCOI2010]传送带

时间:2018-09-02 23:51:26      阅读:187      评论:0      收藏:0      [点我收藏+]

标签:show   sqrt   三分   scan   nbsp   abs   tps   inline   ||   

P2571 [SCOI2010]传送带

三分套三分。

前提条件:P3382 【模板】三分法

三分,求区间内单峰函数的最大/最小值。

我们把两条线段都跑三分,先ab后cd,求出最小值。

可以直接将二维坐标进行三分,为了方便编写,不一定非要取三等分点。代码中取的是中点和一个四等分点。

#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
typedef double db;
inline db _min(const db &a,const db &b) {return a<b ?a:b;}
const db eps=1e-7;
struct node{db x,y;}a,b,c,d; //存坐标
db p,q,r;
inline db dist(node &A,node &B) {return sqrt((A.x-B.x)*(A.x-B.x)+(A.y-B.y)*(A.y-B.y));}
inline db F(node &n,node &m) {return dist(a,n)/p+dist(n,m)/r+dist(m,d)/q;} //总距离计算
inline db sec(node &A){
    node l1=c,r1=d,l2,r2; db ans=1e9;
    do{
        l2.x=(l1.x+r1.x)/2.0,l2.y=(l1.y+r1.y)/2.0;
        r2.x=(l2.x+r1.x)/2.0,r2.y=(l2.y+r1.y)/2.0;
        db q1=F(A,l2),q2=F(A,r2);
        if(q1>q2) l1=l2;
        else r1=r2;
        ans=_min(ans,_min(q1,q2));
    }while(fabs(r1.x-l1.x)>=eps||fabs(r1.y-l1.y)>=eps);
    return ans;
}
int main(){
    scanf("%lf%lf%lf%lf",&a.x,&a.y,&b.x,&b.y);
    scanf("%lf%lf%lf%lf",&c.x,&c.y,&d.x,&d.y);
    scanf("%lf%lf%lf",&p,&q,&r);
    node l1=a,r1=b,l2,r2; db ans=1e9;
    do{
        l2.x=(l1.x+r1.x)/2.0,l2.y=(l1.y+r1.y)/2.0; //取中点
        r2.x=(l2.x+r1.x)/2.0,r2.y=(l2.y+r1.y)/2.0; //取四等分点
        db q1=sec(l2),q2=sec(r2); //在cd上三分
        if(q1>q2) l1=l2;
        else r1=r2;
        ans=_min(ans,_min(q1,q2));
    }while(fabs(r1.x-l1.x)>=eps||fabs(r1.y-l1.y)>=eps); //使用do-while循环是防止线段退化成一个点的情况时直接跳出(如a,b重合)
    printf("%.2lf",ans);
    return 0;
}

 

P2571 [SCOI2010]传送带

标签:show   sqrt   三分   scan   nbsp   abs   tps   inline   ||   

原文地址:https://www.cnblogs.com/kafuuchino/p/9575449.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!