BZOJ P1857:[Scoi2010]传送带

来源:互联网 发布:志鸿优化系列丛书下载 编辑:程序博客网 时间:2024/05/13 13:37

Orz,原来是三分大法,还以为有公式,但是推不出来

据说耗费时间是一个二次函数

设在线段AB上取点(x1,y1),CD上取点(x2,y2);

点A坐标为(ax,ay),点D坐标为(dx,dy)

那么时间就是sqrt((ax-x1)^2+(ay-y1)^2)/p同理,可以发现是二次函数

然后三分在AB上的点,和在CD上的点求出答案即可

下面是代码

#include<iostream>#include<algorithm>#include<cstdio>#include<cmath>using namespace std;const double eps=1e-3;int ax,ay,bx,by,cx,cy,dx,dy,p,q,r;double ans;double dis(double x,double y,double x1,double y1){  double v1=sqrt((x-x1)*(x-x1)+(y-y1)*(y-y1));  return v1;}double work(double sx,double sy,double x,double y){  double res=dis(ax,ay,sx,sy)/p+dis(sx,sy,x,y)/r+dis(x,y,dx,dy)/q;  return res;}double calc(double sx,double sy){  double lx=cx,ly=cy,rx=dx,ry=dy;  while(fabs(lx-rx)>eps||fabs(ly-ry)>eps){   double x1=lx+(rx-lx)/3;double y1=ly+(ry-ly)/3;    double x2=lx+(rx-lx)/3*2;double y2=ly+(ry-ly)/3*2;    if(work(sx,sy,x1,y1)>work(sx,sy,x2,y2)){      lx=x1;ly=y1;    }else{      rx=x2;ry=y2;    }  }  return work(sx,sy,lx,ly);}int main(){cin>>ax>>ay>>bx>>by>>cx>>cy>>dx>>dy>>p>>q>>r;  double lx=ax,ly=ay,rx=bx,ry=by;  while(fabs(lx-rx)>eps||fabs(ly-ry)>eps){    double x1=lx+(rx-lx)/3;double y1=ly+(ry-ly)/3;    double x2=lx+(rx-lx)/3*2;double y2=ly+(ry-ly)/3*2;    if(calc(x1,y1)>calc(x2,y2)){      lx=x1;ly=y1;   }else{      rx=x2;ry=y2;    }  }  ans=min(calc(lx,ly),calc(rx,ry));  printf("%.2lf\n",ans);  return 0;}


0 0