HDU 3400 Line belt【三分法】
题意: 有两条线段,在其中一条线段上移动的速度为 v1,在另一条线上速度为v2, 在其他地方移动速度为 r,问从其中一条线段的一个端点移动到另一个线段
的一个端点的最少时间。
分析: 在其中一条线段上三分离开的点,枚举之后再进行一次三分求最优解,关键在于看出函数是凸性的。
#include<stdio.h> #include<string.h> #include<math.h> const double eps=1e-6; struct node { double x,y; }; double dis(node a,node b) { return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y)); } double v1,v2,R; double tcal(node a,node c,node d) { node l,r; node mid,midmid; double l1,l2; l=c; r=d; while(dis(l,r)>=eps) { mid.x=(l.x+r.x)/2; mid.y=(l.y+r.y)/2; midmid.x=(mid.x+r.x)/2; midmid.y=(mid.y+r.y)/2; l1=dis(a,mid)/R+dis(mid,d)/v2; l2=dis(a,midmid)/R+dis(midmid,d)/v2; if(l1>l2) l=mid; else r=midmid; } return l1; } double cal(node a,node b,node c,node d) { node l,r; node mid,midmid; double l1,l2; l=a; r=b; do { mid.x=(l.x+r.x)/2; mid.y=(l.y+r.y)/2; midmid.x=(mid.x+r.x)/2; midmid.y=(mid.y+r.y)/2; l1=dis(a,mid)/v1+tcal(mid,c,d); l2=dis(a,midmid)/v1+tcal(midmid,c,d); if(l1>l2) l=mid; else r=midmid; }while(dis(r,l)>=eps); return l1; } int main() { node a,b,c,d; 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",&v1,&v2,&R); printf("%.2lf\n",cal(a,b,c,d)); } return 0; }