之前没学过三分,不过猜想过它的那个原理,跟二分的差不多,都是逼近的思想 这次月赛的D题,是三分的,比赛时,搞不出,回来才发现枚举AB的时间可能会逼近不到端点的情况,加了这个判断就过了。。。 回来再试了下两重三分的。。。贴贴代码。。。
 /**//*
题意:有两条线段,AB,CD 在AB上走速度为P,CD上走为Q,其余地方为R
问从A到D的最短时间

三分,可以处理凸函数峰值,及单调函数
m1,m2取法只要在left,right之内就行吧,这里用黄金比例
记住:
如果m1更接近峰值,则去掉m2右边
如果m2更接近峰值,则去掉m1左边
*/
#include<cstdio>
#include<cstring>
#include<cmath>

const double eps=1e-5;

struct Point
  {
double x,y;
}A,B,C,D,AA,DD;

double P,Q,R;

double dist(Point &a,Point &b)
  {
return sqrt(eps+(a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y)); //要加eps 比较那些加不加应该没关系
}
double f(double tc)
  {
DD.x=D.x+(C.x-D.x)/dist(C,D)*tc*Q;
DD.y=D.y+(C.y-D.y)/dist(C,D)*tc*Q;
return tc+dist(AA,DD)/R;
}
int main()
  {
//freopen("in","r",stdin);
int T;
scanf("%d",&T);
 while(T--) {
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);
double ans=1000000000.0;
bool flag=true;
for(double ta=0;flag;ta+=0.01)//枚举在AB走了多长时间
 {
 if(ta>eps+dist(A,B)/P) {//ta>dist(A,B)/P,这样会漏掉了端点,但有可能取到端点,所以要特判!
ta=dist(A,B)/P;
flag=false;
}
AA.x=A.x+(B.x-A.x)/dist(A,B)*ta*P;
AA.y=A.y+(B.y-A.y)/dist(A,B)*ta*P;
double left=0,right=dist(C,D)/Q;
while(right-left>eps)
 {
double m1=right-(right-left)*0.618;
double m2=left+(right-left)*0.618;
if(f(m1)>f(m2)+eps)left=m1;
else right=m2;
}
if(f(left)+ta+eps<ans)ans=f(left)+ta;
}
printf("%.2f\n",ans);
}
return 0;
}
上面那个是枚举在AB走的时间,比较慢,这个两重三分的,0ms
 /**//*
由于有两个自变量ta,tc分别表示在AB,CD上走的时间,需要降维
上面那种是枚举降维,这里对ta也三分来降维,快了好多
*/
#include<cstdio>
#include<cstring>
#include<cmath>

const double eps=1e-5;

struct Point
  {
double x,y;
}A,B,C,D,AA,DD;

double P,Q,R;

double dist(Point &a,Point &b)
  {
return sqrt(eps+(a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y)); //要加eps 比较那些加不加应该没关系
}
double f(double tc)
  {
DD.x=D.x+(C.x-D.x)/dist(C,D)*tc*Q;
DD.y=D.y+(C.y-D.y)/dist(C,D)*tc*Q;
return tc+dist(AA,DD)/R;
}
double cal(double ta)
  {
AA.x=A.x+(B.x-A.x)/dist(A,B)*ta*P;
AA.y=A.y+(B.y-A.y)/dist(A,B)*ta*P;
double left=0,right=dist(C,D)/Q;
while(right-left>eps)
 {
double m1=right-(right-left)*0.618;
double m2=left+(right-left)*0.618;
if(f(m1)>f(m2)+eps)left=m1;
else right=m2;
}
return f(left)+ta;
}
int main()
  {
//freopen("in","r",stdin);
int T;
scanf("%d",&T);
 while(T--) {
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);
double low=0,high=dist(A,B)/P;//注意high是这个,不是无穷,因为限定了在AB内
while(high-low>eps)
 {
double m=high-(high-low)*0.618;
double mm=low+(high-low)*0.618;
if(cal(m)>cal(mm)+eps)low=m;
else high=mm;
}
printf("%.2f\n",cal(low));
}
return 0;
}
|