题目
Problem 947: 传送带
Time Limit: 1000 ms Memory Limit: 256000 KBProblem 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 1Sample Output
136.60对于100%的数据
1<=Ax,Ay,Bx,By,Cx,Cy,Dx,Dy<=1000
1<=P,Q,R<=10Problem 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了……