lightoj 1146 - Closest Distance(三分)

Two men are moving concurrently, one man is moving from A to B and other man is moving from C to D. Initially the first man is at A, and the second man is at C. They maintain constant velocities such that when the first man reaches B, at the same time the second man reaches D. You can assume that A, B, C and D are 2D Cartesian co-ordinates. You have to find the minimum Euclidean distance between them along their path.

Input

Input starts with an integer T (≤ 1000), denoting the number of test cases.

Each case will contain eight integers: Ax, Ay, Bx, By, Cx, Cy, Dx, Dy. All the co-ordinates are between 0 and 100(Ax, Ay) denotes A(Bx, By) denotes B and so on.

Output

For each case, print the case number and the minimum distance between them along their path. Errors less than 10-6 will be ignored.

Sample Input

Output for Sample Input

3

0 0 5 0 5 5 5 0

0 0 5 5 10 10 6 6

0 0 5 0 10 1 1 1

Case 1: 0

Case 2: 1.4142135624

Case 3: 1

 

有两个人,一个人从A出发,一个人从C出发,两个人同时到达B和D,然后让你求两个人之间最小的距离。因为他们之间的距离函数不是单调的,所以不能用二分了,只能用三分。下面来介绍一下三分:
有l,r,令mid = (l + r) / 2,mmid = (mid + r) / 2,如果mid比较靠近极值,那么就让r = mmid,否则就让l = mid;然后就这样一直循环下去,直到精度达到题目的要求。

#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>

using namespace std;
const double eps = 1e-8;
struct node
{
    double x,y;
};

node a,b,c,d;
double dis(node a,node b)
{
    return (a.x-b.x)*(a.x-b.x) + (a.y-b.y)*(a.y-b.y);
}

double cal(double mid)
{
    node p1, p2;
    p1.x = a.x + (b.x - a.x) * mid;
    p1.y = a.y + (b.y - a.y) * mid;
    p2.x = c.x + (d.x - c.x) * mid;
    p2.y = c.y + (d.y - c.y) * mid;
    double d = dis(p1, p2);
    return d;
}

int main(void)
{
    int T;
    scanf("%d",&T);
    int cas = 1;
    while(T--)
    {
        cin >> a.x >> a.y >> b.x >> b.y >> c.x >> c.y >> d.x >> d.y;
        double l = 0,r = 1;
        double ans = r;
        while(r - l > eps)
        {
            double mid = (l + r) /2;
            double mmid = (mid + r)/2;
            if(cal(mid) < cal(mmid))
            {
                ans = mid;
                r = mmid;
            }
            else
                l = mid;
        }
        printf("Case %d: %.6f\n",cas++,sqrt(cal(ans)));
    }

    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值