bzoj1857 [Scoi2010]传送带

Description


在一个2维平面上有两条传送带,每一条传送带可以看成是一条线段。两条传送带分别为线段AB和线段CD。lxhgww在AB上的移动速度为P,在CD上的移动速度为Q,在平面上的移动速度R。现在lxhgww想从A点走到D点,他想知道最少需要走多长时间

对于100%的数据,1<= Ax,Ay,Bx,By,Cx,Cy,Dx,Dy<=1000
1<=P,Q,R<=10

Solution


关键在于找到AB和CD上的两个点E和F,使得A-E-F-D这条路所用时间最短
观察一下可以发现当E固定时F在CD上滑动是一个凹函数,当F固定时E同理,那么三分套三分即可

Code


#include <stdio.h>
#include <string.h>
#include <math.h>
#define rep(i,st,ed) for (int i=st;i<=ed;++i)

const double eps=0.00001;

struct pos {
    double x,y;
    void read() {
        scanf("%lf%lf",&x,&y);
    }
} A,B,C,D;

double P,Q,R;

double get_dis(pos a,pos b) {
    return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}

double check(pos lim) {
    pos l=C,r=D;
    while (get_dis(l,r)>eps) {
        double wx=(r.x-l.x)/3.0;
        double wy=(r.y-l.y)/3.0;
        pos midl=(pos) {l.x+wx,l.y+wy};
        pos midr=(pos) {r.x-wx,r.y-wy};
        double retl=get_dis(A,lim)/P+get_dis(lim,midl)/R+get_dis(midl,D)/Q;
        double retr=get_dis(A,lim)/P+get_dis(lim,midr)/R+get_dis(midr,D)/Q;
        if (retl>=retr) l=midl;
        else r=midr;
    }
    return get_dis(A,lim)/P+get_dis(lim,l)/R+get_dis(l,D)/Q;
}

int main(void) {
    A.read(); B.read();
    C.read(); D.read();
    scanf("%lf%lf%lf",&P,&Q,&R);
    pos l=A,r=B;
    while (get_dis(l,r)>eps) {
        double wx=(r.x-l.x)/3.0;
        double wy=(r.y-l.y)/3.0;
        pos midl=(pos) {l.x+wx,l.y+wy};
        pos midr=(pos) {r.x-wx,r.y-wy};
        double retl=check(midl);
        double retr=check(midr);
        if (retl>=retr) l=midl;
        else r=midr;
    }
    printf("%.2lf\n", check(l));
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值