BNU 51638 Air Hockey 三分二分法

Air Hockey

无聊的过河船同学和无聊的胀鱼同学非常喜欢打桌上冰球(其实只是喜欢听球碰撞时的声音)。在无聊的一天,无聊的过河船同学想到了一个无聊的玩法:两人同时将两个球放桌面上,同时击出,然后听两颗球撞在一起时的声音。然而他们都对击球的精确度把握得不是很好,所以这两颗球并不一定能相撞。

现在假设桌面无限大,并且绝对光滑,给出两球的初始位置、半径和运动速度,保证两球初始没有接触。无聊的过河船同学想知道两球能否相撞(接触即认为相撞),如果能,他想知道两球相撞的时间(从两人击球时开始计时),如果不能,他想知道全过程中两球距离的最小值,这里两球距离的定义为两球上任取两个点的距离的最小值,数据保证这种情况下答案不小于。请注意,冰球是个圆柱体,从空中往下看就是一个圆,且在这个问题中,冰球的高度可以忽略不计。

Input

第一行是一个正整数,表示测试数据的组数,

每组测试数据包含两行,

行包含五个绝对值不大于的整数,表示第个球的初始位置、半径和运动速度。

Output

对于每组测试数据,若两球能相撞,输出两球相撞的时间,否则输出全过程中两球距离的最小值,相对误差不超过即可,

也就是说,令输出结果为,标准答案为,若满足,则输出结果会被认为是正确答案。

Sample Input

2
0 0 2 1 0
11 0 1 -1 0
0 0 2 1 0
11 5 1 -1 0

Sample Output

4.0000000000
2.0000000000

Hint

对于第一组样例,两球在击球后4.0秒时发生碰撞,

对于第二组样例,两球不发生碰撞,且在击球后5.5秒时两球距离最近,此时距离为2.0。

Source

第十四届北京师范大学程序设计竞赛决赛

Author

题解:

  

两个不同大小的圆柱体向不同的方向以不同速度同时出发,问是否能碰撞,不能的话给出最小距离,能的话给出碰撞的时间。

解题思路:

可以证明两球在运动过程中一定是先靠近再变远或者直接一直变远的,所以可以三分运动时间求两圆圆心的最近距离,如果两圆最近距离(圆心最近距离-两圆半径)小于1e-6(题干说的条件),则可以碰撞,再以0~达到最近点的时间为区间二分求出碰撞时间,否则直接输出两圆圆心最近距离减去两圆半径之和。

#include<bits/stdc++.h>
using namespace std;
const int N = 1e6+20, M = 1e6+10, mod = 1e9+7, inf = 1e9+1000;
typedef long long ll;
double x[2], y[2], r[2], vx[2], vy[2];
inline double s(double a)
{
    return a*a;
}
double d(double t)
{
    double x0 = x[0] + vx[0] * t;
    double x1 = x[1] + vx[1] * t;
    double y0 = y[0] + vy[0] * t;
    double y1 = y[1] + vy[1] * t;
    return sqrt(s(x1 - x0) + s(y1 - y0)) - r[0] - r[1];
}
int main()
{
    int T;
    scanf("%d", &T);
    while (T--)
    {
        scanf("%lf%lf%lf%lf%lf", &x[0], &y[0], &r[0], &vx[0], &vy[0]);
        scanf("%lf%lf%lf%lf%lf", &x[1], &y[1], &r[1], &vx[1], &vy[1]);
        double l = 0, r = 1e10;
        while (r - l>1e-7)//先三分找最低点
        {
            double mid1 = l + (r - l) / 3, mid2 = r - (r - l) / 3;
            double ans1 = d(mid1), ans2 = d(mid2);
            if (ans1 <= ans2) r = mid2;
            else l = mid1;
        }
        if (d(l)>=1e-6)printf("%.10lf\n", d(l));
        else//二分找0点
        {
            l = 0;
            while (r - l > 1e-7)
            {
                double mid = (r + l) / 2;
                if (d(mid) > 0)l = mid;
                else r = mid;
            }
            printf("%.10f\n", l);
        }
    }
}
时间: 2024-10-05 05:58:42

BNU 51638 Air Hockey 三分二分法的相关文章

bnu 51638 Air Hockey(三分+二分)(北师16校赛)

无聊的过河船同学和无聊的胀鱼同学非常喜欢打桌上冰球(其实只是喜欢听球碰撞时的声音).在无聊的一天,无聊的过河船同学想到了一个无聊的玩法:两人同时将两个球放桌面上,同时击出,然后听两颗球撞在一起时的声音.然而他们都对击球的精确度把握得不是很好,所以这两颗球并不一定能相撞. 现在假设桌面无限大,并且绝对光滑,给出两球的初始位置.半径和运动速度,保证两球初始没有接触.无聊的过河船同学想知道两球能否相撞(接触即认为相撞),如果能,他想知道两球相撞的时间(从两人击球时开始计时),如果不能,他想知道全过程中

计算几何--bnu51638

Air Hockey Time Limit: 1000ms Memory Limit: 262144KB 64-bit integer IO format: %lld      Java class name: Main Special Judge Prev Submit Status Statistics Discuss Next Type: None None Graph Theory      2-SAT     Articulation/Bridge/Biconnected Compon

BNU 4260 ——Trick or Treat——————【三分求抛物线顶点】

ial Judge Prev Submit Status Statistics Discuss Next Type: None None   Graph Theory       2-SAT       Articulation/Bridge/Biconnected Component       Cycles/Topological Sorting/Strongly Connected Component       Shortest Path           Bellman Ford  

BNU 4260 Trick or Treat &amp;&amp; ZOJ 3386 (三分查找)

[题目链接]click here~~ [题目大意]求x轴上一点到各点的最大值中的最小值 点到线段距离  [解题思路]三分查找 三分查找初学可以参考这篇博客分析:三分查找,写的很详细了,其实跟类似于二分查找,理解了如何构造,代码不难实现 方法1: #include <bits/stdc++.h> using namespace std; const double eps=1e-7; const double inf=0x3f3f3f3f; const int N=55000; int n; st

三分查找

我们都知道 二分查找 适用于单调函数中逼近求解某点的值. 如果遇到凸性或凹形函数时,可以用三分查找求那个凸点或凹点. 下面的方法应该是三分查找的一个变形. 如图所示,已知左右端点L.R,要求找到白点的位置. 思路:通过不断缩小 [L,R] 的范围,无限逼近白点. 做法:先取 [L,R] 的中点 mid,再取 [mid,R] 的中点 mmid,通过比较 f(mid) 与 f(mmid) 的大小来缩小范围. 当最后 L=R-1 时,再比较下这两个点的值,我们就找到了答案. 1.当 f(mid) >

hihoCoder #1142 : 三分求极值

#1142 : 三分·三分求极值 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 这一次我们就简单一点了,题目在此: 在直角坐标系中有一条抛物线y=ax^2+bx+c和一个点P(x,y),求点P到抛物线的最短距离d. 提示:三分法 输入 第1行:5个整数a,b,c,x,y.前三个数构成抛物线的参数,后两个数x,y表示P点坐标.-200≤a,b,c,x,y≤200 输出 第1行:1个实数d,保留3位小数(四舍五入) 样例输入 2 8 2 -2 6 样例输出 2.437

从零基础学三分查找

转载请注明:http://www.cnblogs.com/ECJTUACM-873284962/ 今晚是我们学长第二次讲课,讲了一个三分!认真听了一下,感觉不是很难,可能会比二分还简单些!我就把上课讲的内容归纳为一篇文章概述吧!以后也会重点讲解的! 简单点说二分是查找区间,相当于一次函数,三分就是二次函数了,求它的极值,怎么做,数学常用的是求导,计算机就用查找咯,那么请看下面的简单概述吧! 一. 概念 在二分查找的基础上,在右区间(或左区间)再进行一次二分,这样的查找算法称为三分查找,也就是三分

HDU 4335 Party All the Time(三分|二分)

 #include<cstdio> #include<cstring> #include<cmath> #include<cstdlib> #include<iostream> #include<algorithm> #include<vector> #include<map> #include<queue> #include<stack> #include<string>

[ACM] CSU 1548 Design road (三分)

http://acm.csu.edu.cn/OnlineJudge/problem.php?id=1548 第一次接触三分,题意和代码参考的网上的. 题意:修路:从(0,0)~(x,y),n个数表示有第二行开始有n行表示有n条河,tx是河的起始位置,ty是河的宽度,有水的地方要修桥,而x,y表示修路的端点,C1表示修路每米的花费,C2表示修桥每米的花费,问你最后花费的最少金额! 思路:先把有河的地方都和到一起,然后它的宽度就知道了,那么就把高度三分,找花费最小的点 这里三分求的是最小值. 三分法