HDU-4793 Collision 计算几何 解方程

13 篇文章 0 订阅
5 篇文章 0 订阅

题意

给我们两个大小不同的圆的半径小圆是实心的 大圆是空心的 然后给我们一个小球的半径 小球的初始位置 还有飞碟在x方向和y方向上的速度 小球撞到内实心圆会能量不损失的反弹 问小球任何位置与大圆相交到完全出去的时间是多少

分析

几何题 如何知道时间呢
如果小球与大圆相切或是无交点 那么小球所求的时间是0
如果小球与内圆相切或是无交点 那么小球所求的时间就是在内圆的交点处的两个时间相减
如果小球与内院发生撞击 那么小球回反射 由于能量不递减 并且反射面是个球面 计算时间的范围也是个球面那么也就相当于求怎么进来的大圆 就会反射出一个不同向的相同时间的轨迹 那么我们求出求进来大圆的时间 和小球撞击内圆的时间 两个作差乘2就能得到解
那么问题其实就相当于如何求出交点处的时间点是多少

我们知道小球的运动轨迹以及方程
x = x0 + vxt
y = y0 + vyt
还知道两个圆的方程
x2 + y2 = Rm2
x2 + y2 = R2
由于初始位置,半径已知所以其中唯一的变量就是t
那么我们把运动轨迹方程带入到第一个圆的等式中 求得t 也就是小球经过第一个圆的交点处的t

x0+vxt2 + y+vyt2 = R+r2

我们把运动轨迹方程代入到第二个圆的等式中 求得t也就是小球经过的第二个圆的交点处的t

x0+vxt2 + y+vyt2 = Rm+r2

注意不同情况 我们需要不同的t去求结果
化简可得
(vx2+vy2)t2 + (2yvy+2xvx)t - R+r2 = 0
(vx2+vy2)t2 + (2yvy+2xvx)t - Rm+r2 = 0 <script type="math/tex" id="MathJax-Element-26">0</script>

那么这里就会产生一个问题 如果球轨迹所在直线和内圆相交 但是方向相反 由于代入等式是个二次方的
会无视方向 这里就需要判断下

如果让球动一点 球与内圆圆心的距离边长了 那么就说明永不会相交 直接输出0.000

所以 根据不同情况 解方程即可

CODE

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const double eps = 1e-8;
double dis(double x1,double y1,double x2,double y2){
    return sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));
}
int main()
{
    double Rm,R,r,x,y,vx,vy;
    while(~scanf("%lf%lf%lf%lf%lf%lf%lf",&Rm,&R,&r,&x,&y,&vx,&vy)){
        double ans,C = x*x+y*y-(R+r)*(R+r);
        double B = 2*y*vy+2*x*vx;
        double A = vy*vy+vx*vx;
        double jud = B*B-4*A*C;
        double x2 = x+vx,y2 = y+vy;
        if(dis(x2,y2,0,0)-dis(x,y,0,0)>eps){//判断是否反向
            puts("0.000");
            continue;
        }
        if(jud-0<=eps){
            puts("0.000");
            continue;
        }
        double t1 = (-B-sqrt(jud))/(2*A);
        double t2 = (-B+sqrt(jud))/(2*A);
        double C2 = x*x+y*y-(Rm+r)*(Rm+r);
        double jud2 = B*B-4*A*C2;
        if(jud2-0<=eps){
            printf("%.3lf\n",t2-t1);
            continue;
        }
        double t3 = (-B-sqrt(jud2))/(2*A);
        printf("%.3lf\n",fabs((t1-t3)*2));
    }
    return 0 ;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值