HDU-4793 几何

链接:http://acm.hdu.edu.cn/showproblem.php?pid=4793

题目大意 :有一个圆硬币半径为r,初始位置为x,y,速度矢量为vx,vy,有一个圆形区域(圆心在原点)半径为R,还有一个圆盘(圆心在原点)半径为Rm (Rm < R),圆盘固定不动,硬币撞到圆盘上会被反弹,不考虑能量损失,求硬币在圆形区域内运动的时间。

运动方程:

x’=x+t*vx;
y’=y+t*vy;
r’=r1+r2;
x’^2+y’^2=r’^2;

解法: 解方程,求 (x+vx*t,y+vy*t) 代入圆形区域方程是否有解,如果没解,说明硬币运动轨迹与圆形区域都不相交,答案为0

如果有解,再看代入圆盘有没有解,如果有解,即为两个解的差值*2, 如果没解,那么就是与圆形区域相交的两个点的t的差值。

难点在于如何构造出两个运动轨迹方程,为什么这么构造。

一共四种情况:

第一种:与外圆相离相切,输出0。

第二种:与外圆相交,与内圆相离相切,输出外圆两个解的差的绝对值。

第三种:与外圆相交,与内圆相交,输出外圆两个解的差的绝对值减去内圆两个解的差的绝对值。

第四种:与外圆相交即有两个解,但是两个解都是负的(要么都是负数要么都是正数),也就是说反向运动才能进入大圆,输出0。

#include<bits/stdc++.h>
#define UP(i,l,h) for(int i=l;i<h;i++)
#define W(t) while(t)
using namespace std;
double eps=1e-10;
int sgn(double x)
{
    if(x > eps) return 1;
    if(x < -eps) return -1;
    return 0;
}
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 A1=vx*vx+vy*vy;
        double B1=2*x*vx+2*y*vy;
        double C1=x*x+y*y-(R+r)*(r+R);
        double A2=A1;
        double B2=B1;
        double C2=x*x+y*y-(RM+r)*(RM+r);
        double detla1=B1*B1-4.0*A1*C1;
        double detla2=B2*B2-4.0*A2*C2;
        double s11=(-B1-sqrt(detla1))/(2.0*A1);
        double s12=(-B1+sqrt(detla1))/(2.0*A1);
        double s21=(-B2-sqrt(detla2))/(2.0*A2);
        double s22=(-B2+sqrt(detla2))/(2.0*A2);
        if(sgn(detla1)<=0) //不与圆相交
        {
            printf("0.000\n");
            continue;
        }
        if(sgn(s12)>=0)
        {
            if(sgn(detla2)<=0) //只与外面的圆相交
                printf("%.3f\n",fabs(s11-s12));
            else  //与内外两个圆相交
                printf("%.3f\n",2*fabs(s21-s11));
        }
        else  //反向
            printf("0.000\n");

    }

}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值