三分套三分。
前提条件:P3382 【模板】三分法
三分,求区间内单峰函数的最大/最小值。
我们把两条线段都跑三分,先ab后cd,求出最小值。
可以直接将二维坐标进行三分,为了方便编写,不一定非要取三等分点。代码中取的是中点和一个四等分点。
#include<cstdio> #include<cmath> #include<algorithm> using namespace std; typedef double db; inline db _min(const db &a,const db &b) {return a<b ?a:b;} const db eps=1e-7; struct node{db x,y;}a,b,c,d; //存坐标 db p,q,r; inline db dist(node &A,node &B) {return sqrt((A.x-B.x)*(A.x-B.x)+(A.y-B.y)*(A.y-B.y));} inline db F(node &n,node &m) {return dist(a,n)/p+dist(n,m)/r+dist(m,d)/q;} //总距离计算 inline db sec(node &A){ node l1=c,r1=d,l2,r2; db ans=1e9; do{ l2.x=(l1.x+r1.x)/2.0,l2.y=(l1.y+r1.y)/2.0; r2.x=(l2.x+r1.x)/2.0,r2.y=(l2.y+r1.y)/2.0; db q1=F(A,l2),q2=F(A,r2); if(q1>q2) l1=l2; else r1=r2; ans=_min(ans,_min(q1,q2)); }while(fabs(r1.x-l1.x)>=eps||fabs(r1.y-l1.y)>=eps); return ans; } int main(){ 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); node l1=a,r1=b,l2,r2; db ans=1e9; do{ l2.x=(l1.x+r1.x)/2.0,l2.y=(l1.y+r1.y)/2.0; //取中点 r2.x=(l2.x+r1.x)/2.0,r2.y=(l2.y+r1.y)/2.0; //取四等分点 db q1=sec(l2),q2=sec(r2); //在cd上三分 if(q1>q2) l1=l2; else r1=r2; ans=_min(ans,_min(q1,q2)); }while(fabs(r1.x-l1.x)>=eps||fabs(r1.y-l1.y)>=eps); //使用do-while循环是防止线段退化成一个点的情况时直接跳出(如a,b重合) printf("%.2lf",ans); return 0; }