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 }