BZOJ1857 SCOI2010 传送带 三分套三分

大家都很强, 可与之共勉 。

题意:
  给您两条线段,分别为 AB,CD (给出 A,B,C,D 的坐标),您要从 A 走到D,给出在线段 AB 的移动速度 P ,线段CD的移动速度 Q ,以及线段外的移动速度R,求最短时间。

题解:
  当在 AB 上固定一点时,我们会发现在另一条线段的点的位置与花费的时间是一个单峰函数,在 BD 上同理,于是我们可以三分。由物理模型构建出三分,或者呃,打表发现是三分的。

坑点:
  这道题可能有线段是一个点,所以三分写成是 dowhile 最好。

/**************************************************************
    Problem: 1857
    User: Lazer2001
    Language: C++
    Result: Accepted
    Time:32 ms
    Memory:1292 kb
****************************************************************/

# include <bits/stdc++.h>

const double eps = 1e-8 ;

struct Point  {
    double x, y ;
    Point ( )  {    }
    Point ( double x, double y ) : x ( x ), y ( y )  {  }
    inline Point operator + ( const Point& rhs )  const  {
        return Point ( x + rhs.x, y + rhs.y ) ;
    }
    inline Point operator - ( const Point& rhs )  const  {
        return Point ( x - rhs.x, y - rhs.y ) ;
    }
    inline Point operator / ( const double& k )  const  {
        return Point ( x / k, y / k ) ;
    }
    inline double operator * ( const Point& rhs )  const  {
        return x * rhs.x + y * rhs.y ;
    }
} p [5] ;

inline double dis ( const Point& a, const Point& b )  {
    return sqrt ( ( a - b ) * ( a - b ) ) ;
}

double v1, v2, v3 ;

inline double TriDivid ( const Point& cur )  {
    Point l = p [2], r = p [3] ;
    Point l2, r2, mid ;
    double ans = 1e16 ;
    do  {
        mid = ( r - l ) / 3 ;
        l2 = l + mid, r2 = r - mid ;
        double rt1 = dis ( p [0], cur ) / v1 + dis ( cur, l2 ) / v3 + dis ( l2, p [3] ) / v2 ;
        double rt2 = dis ( p [0], cur ) / v1 + dis ( cur, r2 ) / v3 + dis ( r2, p [3] ) / v2 ;
        ( rt1 < rt2 ) ? r = r2 : l = l2 ;
        ans = std :: min ( rt1, rt2 ) ;
    }  while ( dis ( l, r ) > eps ) ;
    return ans ;
}

int main ( )  {
    for ( int i = 0 ; i < 4 ; ++ i )  {
        static double x, y ;
        scanf ( "%lf%lf", & x, & y ) ;
        p [i] = Point ( x, y ) ;
    }

    scanf ( "%lf%lf%lf", & v1, & v2, & v3 ) ;

    Point l = p [0], r = p [1] ;

    double ans = 1e16 ;

    do  {
        Point l2, r2, mid ;
        mid = ( r - l ) / 3 ;
        l2 = l + mid, r2 = r - mid ;
        double ans1 = TriDivid ( l2 ) ;
        double ans2 = TriDivid ( r2 ) ;
        ( ans1 < ans2 ) ? r = r2 : l = l2 ;
        ans = std :: min ( ans1, ans2 ) ;
    }   while ( dis ( l, r ) > eps ) ;

    return printf ( "%.2lf\n", ans ), 0 ;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值