Collision UVALive - 6613 (数学几何)

本文介绍了一种计算硬币在特定区域内滑动时间的方法,包括硬币与障碍物碰撞后的反弹过程。通过解析硬币的初始位置和速度矢量,确定硬币进入和离开指定区域的时间。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

There’s a round medal fixed on an ideal smooth table, Fancy is trying to throw some coins and make
them slip towards the medal to collide. There’s also a round range which shares exact the same center
as the round medal, and radius of the medal is strictly less than radius of the round range. Since that
the round medal is fixed and the coin is a piece of solid metal, we can assume that energy of the coin
will not lose, the coin will collide and then moving as reflect.
Now assume that the center of the round medal and the round range is origin (Namely (0, 0)) and
the coin’s initial position is strictly outside the round range. Given radius of the medal Rm, radius of
coin r, radius of the round range R, initial position (x, y) and initial speed vector (vx, vy) of the coin,
please calculate the total time that any part of the coin is inside the round range.
Please note that the coin might not even touch the medal or slip through the round range.

Input
There will be several test cases. Each test case contains 7 integers Rm, R, r, x, y, vx and vy in one
line. Here 1 ≤ Rm < R ≤ 2000, 1 ≤ r ≤ 1000, R + r < |(x, y)| ≤ 20000, 1 ≤ |(vx, vy)| ≤ 100.
Output
For each test case, please calculate the total time that any part of the coin is inside the round range.
Please output the time in one line, an absolute error not more than 1e-3 is acceptable.
Sample Input
5 20 1 0 100 0 -1
5 20 1 30 15 -1 0
Sample Output
30.000
29.394

大致题意:在光滑的桌面上固定了一个半径为Rm的圆盘,圆心在坐标(0,0)处,有一个半径为R圆心也在(0,0)的圆形范围。现在在这个圆形范围外有一个半径为r的圆形硬币,告诉你它的圆心坐标和速度矢量,问这个圆形硬币在这个圆形范围内经过的时间,如果与中心圆盘相撞,那么会以相同的速度原路返回。

思路:已知硬币的圆心坐标和它的速度矢量,所以我们可以很容易的求出硬币圆心的运动直线方程,假设直线方程为y=k*x+b,那么k=vy/vx,b=y0-k*x0。然后我们求下硬币与圆形范围相切时候的硬币圆心的坐标,即找出该直线上的点(x,y)使得它到点(0,0)的距离为(R+r),列个方程解下就可以了,如果有解的话会是两个坐标,如果无解的话则说明不经过。接着我们判断下这两个坐标与起始坐标之间的大小关系,判断是否满足速度矢量,如果不满足说明也不经过。然后接着按照相同的方法求硬币与圆盘相切时的硬币圆心坐标。如果无解,说明硬币是直接从圆形范围内穿过,那么所花时间即之前所求得的两个相切点之间的的距离除以速度,如果有解,则说明硬币会和它相撞,然后按原路返回,所花时间即离起点最近的两个切点(一个圆形范围的切点,一个圆盘的切点)间的距离除以速度乘再2。

代码如下

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <vector>
#include <queue>
#include <cmath>
#include <cstring>
using namespace std;

int R1,R2,r,x,dx,y,dy;
double max(double q1,double q2)
{
    if(q1>q2) return q1;
    else return q2;
}
double min(double q1,double q2)
{
    if(q1<q2) return q1;
    else return q2;
}

int main()
{
    while(scanf("%d%d%d%d%d%d%d",&R1,&R2,&r,&x,&y,&dx,&dy)!=EOF)
    {
        if(dx!=0)//考虑下直线斜率是否存在,如果存在
        {
            double k=dy*1.0/dx;
            double b=y-k*x;

            double ans=((R2+r)*(R2+r)+k*k*b*b/(k*k+1)-b*b)/(k*k+1);
            if(ans<=0)//如果无解
            {
                printf("0.000\n");
                continue;
            }
            ans=sqrt(ans);
            double a1=ans-k*b/(k*k+1);
            double a2=-ans-k*b/(k*k+1);
            double x1=max(a1,a2);
            double x2=min(a1,a2);
            if(dx>0&&x>x1)//判断下两个切点坐标和起点之间的大小关系是否满足速度矢量
            {
                printf("0.000\n");
                continue;
            }
            if(dx<0&&x<x2)
            {
                printf("0.000\n");
                continue;
            }

            double ans2=((R1+r)*(R1+r)+k*k*b*b/(k*k+1)-b*b)/(k*k+1);
            if(ans2<=0)//如果无解,说明硬币没有碰撞上圆盘,直接从圆形范围中穿出
            {
                if(dx<0)
                dx=-dx;
                printf("%.3lf\n",(x1-x2)/dx);
            }
            else
            {
                ans2=sqrt(ans2);
                a1=ans2-k*b/(k*k+1);
                a2=-ans2-k*b/(k*k+1);
                double x3=max(a1,a2);
                double x4=min(a1,a2);
                if(dx<0)

                    printf("%.3lf\n",-2*(x1-x3)/dx);
                else 
                    printf("%.3lf\n",2*(x4-x2)/dx);

            }
        }
        else //如果直线斜率不存在
        {
            double ans=(R2+r)*(R2+r)-x*x;
            if(ans<=0)
            {
                printf("0.000\n");
                continue;
            }
            double y1=sqrt(ans);
            double y2=-sqrt(ans);

            if(dy<0&&y<y1)
            {
                printf("0.000\n");
                continue;
            }
            if(dy>0&&y>y1)
            {
                printf("0.000\n");
                continue;
            }

            double ans2=(R1+r)*(R1+r)-x*x;
            if(ans2<=0)
            {
                if(dy<0)
                dy=-dy;
                printf("%.3lf\n",(y1-y2)/dy);
            }
            else
            {
                double y3=sqrt(ans2);
                double y4=-sqrt(ans2);
                if(dy<0)
                    printf("%.3lf\n",-2*(y1-y3)/dy);
                else 
                    printf("%.3lf\n",2*(y4-y2)/dy);

            }
        }
    }
    return 0;
}
内容概要:本文档详细介绍了Analog Devices公司生产的AD8436真均方根-直流(RMS-to-DC)转换器的技术细节及其应用场景。AD8436由三个独立模块构成:轨到轨FET输入放大器、高动态范围均方根计算内核和精密轨到轨输出放大器。该器件不仅体积小巧、功耗低,而且具有广泛的输入电压范围和快速响应特性。文档涵盖了AD8436的工作原理、配置选项、外部组件选择(如电容)、增益调节、单电源供电、电流互感器配置、接地故障检测、三相电源监测等方面的内容。此外,还特别强调了PCB设计注意事项和误差源分析,旨在帮助工程师更好地理解和应用这款高性能的RMS-DC转换器。 适合人群:从事模拟电路设计的专业工程师和技术人员,尤其是那些需要精确测量交流电信号均方根值的应用开发者。 使用场景及目标:①用于工业自动化、医疗设备、电力监控等领域,实现对交流电压或电流的精准测量;②适用于手持式数字万用表及其他便携式仪器仪表,提供高效的单电源解决方案;③在电流互感器配置中,用于检测微小的电流变化,保障电气安全;④应用于三相电力系统监控,优化建立时间和转换精度。 其他说明:为了确保最佳性能,文档推荐使用高质量的电容器件,并给出了详细的PCB布局指导。同时提醒用户关注电介质吸收和泄漏电流等因素对测量准确性的影响。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值