GalaxyOJ-947 (三分)

来源:互联网 发布:淘宝买游戏账号被找回 编辑:程序博客网 时间:2024/05/17 08:47

题目

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了……