BZOJ1857 [Scoi2010]传送带[三分]

单峰函数的求极值一般采用三分法(当然求导然后二分零点也是可以的。。)。

这题的行走方式一定是先走AB一段,然后离开,走到CD上,然后再在CD上走到D点。

所以可以看成有三条线段,答案为$|AP|/p+|PQ|/r+|RD|/q$。然后这个不妨先固定P点。

然后后面这个两端线段的比例之和是一个单谷函数,也就是只有一个极小值。

所以对于每个P点,有一个对应的后面两项的最小值,而再加上第一项之后,仍是一个单谷函数。

所以每次P的三分中在套一个Q的三分即可。

关于为什么是单谷函数:不会证。使用几何画板的绘制函数以及线段转化(初中学的构造转化线段。。)发现是没有问题的。。

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 #include<cmath>
 6 #include<queue>
 7 #define mst(x) memset(x,0,sizeof x)
 8 #define dbg(x) cerr << #x << " = " << x <<endl
 9 #define dbg2(x,y) cerr<< #x <<" = "<< x <<"  "<< #y <<" = "<< y <<endl
10 using namespace std;
11 typedef long long ll;
12 typedef double db;
13 typedef pair<int,int> pii;
14 template<typename T>inline T _min(T A,T B){return A<B?A:B;}
15 template<typename T>inline T _max(T A,T B){return A>B?A:B;}
16 template<typename T>inline char MIN(T&A,T B){return A>B?(A=B,1):0;}
17 template<typename T>inline char MAX(T&A,T B){return A<B?(A=B,1):0;}
18 template<typename T>inline void _swap(T&A,T&B){A^=B^=A^=B;}
19 template<typename T>inline T read(T&x){
20     x=0;int f=0;char c;while(!isdigit(c=getchar()))if(c=='-')f=1;
21     while(isdigit(c))x=x*10+(c&15),c=getchar();return f?x=-x:x;
22 }
23 const db eps=1e-7;
24 db ax,ay,bx,by,cx,cy,dx,dy,p,q,r;
25 inline db dis(db x,db y,db xx,db yy){return sqrt((xx-x)*(xx-x)+(yy-y)*(yy-y));}
26 inline db divide(db x,db y){return x+(y-x)/3;}
27 inline db divide2(db x,db y){return x+(y-x)*2/3;}
28 inline db dist(db x,db y){//dbg2(x,y);
29     db lx=cx,ly=cy,rx=dx,ry=dy;
30     for(register int i=1;i<=100;++i){
31         db lmidx=divide(lx,rx),rmidx=divide2(lx,rx),lmidy=divide(ly,ry),rmidy=divide2(ly,ry);
32     //    dbg2(lmidx,lmidy),dbg2(rmidx,rmidy);
33         if(dis(lmidx,lmidy,x,y)/r+dis(lmidx,lmidy,dx,dy)/q>dis(rmidx,rmidy,x,y)/r+dis(rmidx,rmidy,dx,dy)/q)lx=lmidx,ly=lmidy;
34         else rx=rmidx,ry=rmidy;
35     }//dbg2(lx,ly);
36     return dis(lx,ly,x,y)/r+dis(lx,ly,dx,dy)/q;
37 }
38 
39 int main(){//freopen("test.in","r",stdin);//freopen("test.ans","w",stdout);
40     scanf("%lf%lf%lf%lf%lf%lf%lf%lf%lf%lf%lf",&ax,&ay,&bx,&by,&cx,&cy,&dx,&dy,&p,&q,&r);
41     db lx=ax,ly=ay,rx=bx,ry=by;
42     for(register int i=1;i<=100;++i){
43         db lmidx=divide(lx,rx),rmidx=divide2(lx,rx),lmidy=divide(ly,ry),rmidy=divide2(ly,ry);
44         if(dist(lmidx,lmidy)+dis(lmidx,lmidy,ax,ay)/p>dist(rmidx,rmidy)+dis(rmidx,rmidy,ax,ay)/p)lx=lmidx,ly=lmidy;
45         else rx=rmidx,ry=rmidy;
46     }
47     printf("%.2f",dis(lx,ly,ax,ay)/p+dist(lx,ly));
48     return 0;
49 }
View Code

 

posted @ 2019-11-05 11:17  Ametsuji_akiya  阅读(127)  评论(0编辑  收藏  举报