GalaxyOJ-947 (三分)

题目

Problem 947: 传送带
Time Limit: 1000 ms Memory Limit: 256000 KB

Problem Description

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

Input

输入数据第一行是4个整数,表示A和B的坐标,分别为Ax,Ay,Bx,By 第二行是4个整数,表示C和D的坐标,分别为Cx,Cy,Dx,Dy 第三行是3个整数,分别是P,Q,R

Output

输出数据为一行,表示lxhgww从A点走到D点的最短时间,保留到小数点后2位

Sample Input

0 0 0 100
100 0 100 100
2 2 1

Sample Output
136.60

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

Problem Source
NOIP2017多校联测&提高组模拟16

分析

  • 我们发现,对于一条线段,从一端点到中间一点再出去到外面某一点,随着中间那个点的变化,得到的时间会是一个单峰函数(当然有可能最值会超出这条线段,但也不影响三分)
  • 对两条线段都三分,(三分套三分),即先三分 AB 的离开点,在这基础上求出 CD 上的最小时间。

程序

#include <cstdio>
#include <cmath>
using namespace std;
struct zzk{double x,y;} A,B,C,D,L,R,M1,M2,m1,m2,l,r;
double ans,ret,PP,QQ,RR,F1,F2,f1,f2;
int i,j;

double dis(zzk x,zzk y){return sqrt((x.x-y.x)*(x.x-y.x)+(x.y-y.y)*(x.y-y.y));}

double f(zzk x){
    for (l=C,r=D,j=1; j<=100; j++){
        m1=(zzk){l.x+(r.x-l.x)/3,l.y+(r.y-l.y)/3},m2=(zzk){l.x+(r.x-l.x)*2/3,l.y+(r.y-l.y)*2/3};
        f1=dis(A,x)/PP+dis(x,m1)/RR+dis(m1,D)/QQ;
        f2=dis(A,x)/PP+dis(x,m2)/RR+dis(m2,D)/QQ;
        if (f1<f2){r=m2; ret=f1; continue;}
        l=m1; ret=f2;
    }
    return ret;
}

int main(){
    scanf("%lf%lf%lf%lf%lf%lf%lf%lf",&A.x,&A.y,&B.x,&B.y,&C.x,&C.y,&D.x,&D.y);
    scanf("%lf%lf%lf",&PP,&QQ,&RR);
    for (L=A,R=B,i=1; i<=0; i++){
        M1=(zzk){L.x+(R.x-L.x)/3,L.y+(R.y-L.y)/3},M2=(zzk){L.x+(R.x-L.x)*2/3,L.y+(R.y-L.y)*2/3};
        F1=f(M1);
        F2=f(M2);
        if (F1<F2){R=M2; ans=F1; continue;}
        L=M1; ans=F2;
    }
    printf("%.2f",ans);
}

提示

  • 之前都是二分,直接 m=(l+r)/1,而这次第一次打三分,应该是 m1=l+(r-l)/3,m2=l+(r-l)*2/3,而一开始我直接(l+r)/3了,结果WA了……
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值