HDU 3400 - Line belt (三分)

Problem Description
In a two-dimensional plane there are two line belts, there are two segments AB and CD, lxhgww's speed on AB is P and on CD is Q, he can move with the speed R on other area on the plane.
How long must he take to travel from A to D?
 

Input
The first line is the case number T.
For each case, there are three lines.
The first line, four integers, the coordinates of A and B: Ax Ay Bx By.
The second line , four integers, the coordinates of C and D:Cx Cy Dx Dy.
The third line, three integers, P Q R.
0<= Ax,Ay,Bx,By,Cx,Cy,Dx,Dy<=1000
1<=P,Q,R<=10
 

Output
The minimum time to travel from A to D, round to two decimals.
 

Sample Input
  
  
1 0 0 0 100 100 0 100 100 2 2 1
 

Sample Output
  
  
136.60

---------------------------------------

题意:

在ab上的速度为p,cd上的速度为q,其他路为r,求出从a到d的最少用时。

思路:

在ab上找到一点e, cd上找到一点f, 使得 ae/p + ef/r + fd/q最小,t1 = ae / p, 线性; t2 = ef/r + fd/ q, 递减到递增函数。分别在ab 和 cd上 使用三分(嵌套三分),找到最佳的e ,f点。

eps = 1e-8. 精度不够会WA。

CODE:

#include <iostream>
#include <cstdio>
#include <cmath>

using namespace std;
const double eps = 1e-8;

struct Point {
    double x, y;
};
double p, q, r;
Point a, b, c, d, e, f;

double dis(Point u, Point v)
{
    return sqrt((u.x - v.x)*(u.x - v.x) + (u.y - v.y)*(u.y - v.y));
}
double cal(double m)
{
    f.x = c.x + (d.x - c.x) * m;
    f.y = c.y + (d.y - c.y) * m;
    return dis(f, d) / q + dis(f, e) / r;
}
double road(double m)
{
    e.x = a.x + (b.x - a.x) * m;
    e.y = a.y + (b.y - a.y) * m;

    double l =0.0, r = 1.0, mid, mmid;
    while(r - l > eps) {
        mid = (l + r)/2.0;
        mmid = (mid+r)/2.0;
        if(cal(mid) < cal(mmid)) r = mmid;
        else l = mid;
    }
    return cal(l) + dis(a, e) / p;
}
void solve()
{
    double l = 0.0, r = 1.0, mid, mmid;
    while(r - l > eps) {
        mid = (l + r) / 2.0;
        mmid = (r + mid) / 2.0;
        if(road(mid) < road(mmid)) r = mmid;
        else l = mid;
     }
     printf("%.2lf\n", road(l));
}
int main()
{
//freopen("in", "r", stdin);
    int T;
    scanf("%d", &T);
    while(T--) {
        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);
        solve();
    }

    return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值