HDU5572(计算几何+精度)

原题:HDU5572

关于精度:关于精度


点关于直线对称公式:

点( x , y )关于直线Ax + by + C = 0 的对称点( X , Y ):


设参数方程


联立圆方程得到关于t的一元二次方程


可见c>0恒成立

分两种情况讨论:

1.小球不反弹

2(1).小球在反弹前已经经过B点

(2).小球反弹后经过b点


对于1,直接检验B是否在射线上(t > 0)

对于2:

要使方程有两个正根,则-b/2a>0,即b<0

其中有效根为较小的t

进而求出反弹点P及切线方程Ax+By+C=0

求出B关于切线对称点C,

检验C是否在射线A上



#include<cstdio>
#include<cstdlib>
#include<iomanip>
#include<iostream>
#include<cstring>
#include<vector>
#include<map>
#include<queue>
#include<stack>
#include<cmath>
#include<algorithm>
using namespace std;
typedef long long ll;
typedef long double ld;
const ld eps=1e-8;
int sgn(ld x)
{
    if(fabs(x)<=eps)
    return 0;
    else
    return x>0?1:-1;
}
int main()
{
    int T,cas=1;
    scanf("%d",&T);
    ld ax,ay,bx,by,ox,oy,vx,vy,r;
    ld a,b,c;
    ld px,py,t,cx,cy,A,B,C,tp;
    while(T--)
    {
        cin>>ox>>oy>>r;
        cin>>ax>>ay>>vx>>vy;
        cin>>bx>>by;
        printf("Case #%d: ",cas++);
        a=vx*vx+vy*vy;
        b=2*(ax*vx-ox*vx+ay*vy-oy*vy);
        c=ax*ax-2*ox*ax+ox*ox+ay*ay-2*oy*ay+oy*oy-r*r;
        if(sgn(b*b-4*a*c)>0&&sgn(b)<0)
        {
            tp=(-b-sqrt(b*b-4*a*c))/(2.0*a);
            px=ax+vx*tp;
            py=ay+vy*tp;
            if(sgn(vx)!=0)
            {
                t=(bx-ax)/vx;
                if(sgn(by-ay-vy*t)==0&&sgn(t-tp)<=0)
                {
                    printf("Yes\n");
                    continue;
                }
            }
            else if(sgn(vy)!=0)
            {
                t=(by-ay)/vy;
                if(sgn(bx-ax-vx*t)==0&&sgn(t-tp)<=0)
                {
                    printf("Yes\n");
                    continue;
                }
            }
            A=ox-px;
            B=oy-py;
            C=py*(py-oy)+px*(px-ox);
            cx=bx-2.0*A*(A*bx+B*by+C)/(A*A+B*B);
            cy=by-2.0*B*(A*bx+B*by+C)/(A*A+B*B);
            if(sgn(vx)!=0)
            {
                t=(cx-ax)/vx;
                if(sgn(cy-ay-vy*t)==0&&sgn(t)>0)
                printf("Yes\n");
                else
                printf("No\n");
            }
            else if(sgn(vy)!=0)
            {
                t=(cy-ay)/vy;
                if(sgn(cx-ax-vx*t)==0&&sgn(t)>0)
                printf("Yes\n");
                else
                printf("No\n");
            }
        }
        else
        {
            if(sgn(vx)!=0)
            {
                t=(bx-ax)/vx;
                if(sgn(by-ay-vy*t)==0&&sgn(t)>0)
                printf("Yes\n");
                else
                printf("No\n");
            }
            else if(sgn(vy)!=0)
            {
                t=(by-ay)/vy;
                if(sgn(bx-ax-vx*t)==0&&sgn(t)>0)
                printf("Yes\n");
                else
                printf("No\n");
            }
        }
    }
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值