1. 程式人生 > >BZOJ 1857 [Scoi2010]傳送帶 三分套三分

BZOJ 1857 [Scoi2010]傳送帶 三分套三分

Description

在一個2維平面上有兩條傳送帶,每一條傳送帶可以看成是一條線段。兩條傳送帶分別為線段AB和線段CD。lxhgww在AB上的移動速度為P,在CD上的移動速度為Q,在平面上的移動速度R。現在lxhgww想從A點走到D點,他想知道最少需要走多長時間

Input

輸入資料第一行是4個整數,表示A和B的座標,分別為Ax,Ay,Bx,By 第二行是4個整數,表示C和D的座標,分別為Cx,Cy,Dx,Dy 第三行是3個整數,分別是P,Q,R

Output

輸出資料為一行,表示lxhgww從A點走到D點的最短時間,保留到小數點後2位

Sample Input

0 0 0 100
100 0 100 100
2 2 1


Sample Output

136.60

HINT

對於100%的資料,1<= Ax,Ay,Bx,By,Cx,Cy,Dx,Dy<=1000
1<=P,Q,R<=10

傳送門 簡單yy證明一下,從A到D的路程一定是AB上一段,平面內一段,CD上一段的。 也就是說不存在“折返”的情況。 那麼假設AB上從A連續走到了(x1,y1),然後在CD上走到(x2,y2)後走到了D, 寫一下距離的表示式,把距離分成3段(省去開根): (Ax,Ay)~(x1,y1):(x1-Ax)^2+(y1-Ay)^2 (x1,y1)~(x2,y2):(x1-x2)^2+(y1-y2)^2
(x2,y2)~(Dx,Dy):(x2-Dx)^2+(y2-Dy)^2 時間就是距離除以上面的速度了,因為是常量,就不表示了。 假設我們列舉一下AB上的那個點(x1,y1),那麼未知量就是(x2,y2)了, 其它量都看做已知量,我們得到了一個二元式f(x,y)=ax^2+by^2+cx+dy+e 由於是在一條線段上的(woc一開始沒看見死活不會……) 所以實際上y和x有一個一次關係,這個二元式實際上是一個二次函式…… 也就是說……單峰! 發現x^2前面的係數是正的,所以是下凸的,,那麼(x2,y2)就可以簡單地三分出來了。 但是直接列舉(x1,y1)似乎太慢了,於是就去猜想是不是也可以三分。
事實上和上面那個是類似的…… 可以考慮固定一個最優的(x2,y2)來看。 所以就是三分(x1,y1),同時三分(x2,y2)了,所謂“三分套三分” 只要注意是個下凸的函式就好了其它也沒什麼。。
#include<bits/stdc++.h>
using namespace std;
const double
    eps=1e-4;
double P,Q,R,Ax,Ay,Bx,By,Cx,Cy,Dx,Dy;
double dis(double x1,double y1,double x2,double y2){
    return sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));
}
double Work_CD(double x,double y){
    double Lx=Cx,Ly=Cy,Rx=Dx,Ry=Dy;
    while (fabs(Lx-Rx)>eps || fabs(Ly-Ry)>eps){
        double lxmid=Lx+(Rx-Lx)/3.0,lymid=Ly+(Ry-Ly)/3.0,
            rxmid=Lx+(Rx-Lx)/3.0*2.0,rymid=Ly+(Ry-Ly)/3.0*2.0;
        if (dis(x,y,lxmid,lymid)/R+dis(Dx,Dy,lxmid,lymid)/Q>
            dis(x,y,rxmid,rymid)/R+dis(Dx,Dy,rxmid,rymid)/Q)
                Lx=lxmid,Ly=lymid;
             else
                Rx=rxmid,Ry=rymid;
    }
    return dis(x,y,Lx,Ly)/R+dis(Dx,Dy,Lx,Ly)/Q;
}
double Work_AB(){
    double Lx=Ax,Ly=Ay,Rx=Bx,Ry=By;
    while (fabs(Lx-Rx)>eps || fabs(Ly-Ry)>eps){
        double lxmid=Lx+(Rx-Lx)/3.0,lymid=Ly+(Ry-Ly)/3.0,
            rxmid=Lx+(Rx-Lx)/3.0*2.0,rymid=Ly+(Ry-Ly)/3.0*2.0;
        if (dis(Ax,Ay,lxmid,lymid)/P+Work_CD(lxmid,lymid)>
            dis(Ax,Ay,rxmid,rymid)/P+Work_CD(rxmid,rymid))
                Lx=lxmid,Ly=lymid;
            else
                Rx=rxmid,Ry=rymid;
    }
    return dis(Ax,Ay,Lx,Ly)/P+Work_CD(Lx,Ly);
}
int main(){
    scanf("%lf%lf%lf%lf",&Ax,&Ay,&Bx,&By);
    scanf("%lf%lf%lf%lf",&Cx,&Cy,&Dx,&Dy);
    scanf("%lf%lf%lf",&P,&Q,&R);
    printf("%.2lf\n",Work_AB());
    return 0;
}