计算几何--bnu51638

来源:互联网 发布:白狐小说系统源码 编辑:程序博客网 时间:2024/02/24 02:52

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
     

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

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

    Input

    第一行是一个正整数T(\leq 10000),表示测试数据的组数,

    每组测试数据包含两行,

    i行包含五个绝对值不大于1000的整数x[i],y[i],r[i],vx[i],vy[i],表示第i个球的初始位置、半径和运动速度。

    Output

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

    也就是说,令输出结果为a,标准答案为b,若满足\frac{ \left | a-b \right | }{max(1,b)} \leq 10^{-6},则输出结果会被认为是正确答案。

    Sample Input

    20 0 2 1 011 0 1 -1 00 0 2 1 011 5 1 -1 0

    Sample Output

    4.00000000002.0000000000

    Hint

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

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

    Source

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

    Author

    quailty
    解:

    设时间为t时两个球相撞或者两个球距离最近,用t可以表示出两个球的坐标 Q1( x1+t*vx1  ,  y1+t*vy1)  Q2(  x2+t*vx2   ,    y2+t*vy2)  ,

    Q1Q2的距离=  aqrt{(x1-x2)^2  +(y1-y2)^2   } =r1+r2;     整理方程得到一个关于t 的一元二次方程  sqrt( a t^2  +  b t + c )=  r1+r2;

    求解该方程,分a=0和a!=0,a!=0,求解 △<0,△=0,△>0,当△<0时无解,求解方程左边的最小值 ,即 t = -b/(2*a),t>0, 带入方程得 d= sqrt ((4ac-b^2)/(4a) ),ans=d-(r1+r2);   t<0 ,ans=sqrt(c)-(r1+r2) 。 当△>=0时,ans=min(t1,t2)。当a=0,时,ans=sqrt(c)-(r1+r2)。

    又复习了一遍初中知识

    #include <iostream>#include <stdio.h>#include <math.h>#include <string.h>using namespace std;double solve(double a,double b,double c){    double dat=b*b-4.0*a*c;    if(dat<0)        return -1;    double x1= ( -b+sqrt(dat) )/2.0/a;    double x2= ( -b-sqrt(dat) )/2.0/a;     if(x2>=0.0)    return x2;    if(x2<0&&x1>0)        return x1;    if(x1<0&&x2<0)        return -1;}int main(){    int t;    double x1,y1,r1,vx1,vy1;    double x2,y2,r2,vx2,vy2;    double x,vx,y,vy;    double a,b,c;    double R;    scanf("%d",&t);    while(t--)    {        scanf("%lf%lf%lf%lf%lf",&x1,&y1,&r1,&vx1,&vy1);        scanf("%lf%lf%lf%lf%lf",&x2,&y2,&r2,&vx2,&vy2 );        x=x1-x2;///c        y=y1-y2;///c        vx=vx1-vx2;///a        vy=vy1-vy2;///a        a=vx*vx+vy*vy;        c=x*x+y*y;        b=2.0*(x*vx+y*vy);        R=1.0*(r1+r2)*(r1+r2);        double t=-1.0*b/2.0/a;        if(a!=0)        {            double ans=solve(a,b,c-R);            if(ans<0&&t<0)            printf("%.10lf\n",sqrt(c)-r1-r2);            if(ans<0&&t>=0)            printf("%.10lf\n",sqrt( (4.0*a*c-b*b) /(4.0*a) )-r1-r2);            if(ans>=0)            printf("%.10lf\n",ans);        }        else        printf("%.10lf\n",sqrt(c)-r1-r2);    }    return 0;}


    1 0
    原创粉丝点击