B - Collision ZOJ - 3728 --几何

题目链接

题意:给一个圆心在原点的印章和圆圈范围,印章的半径Rm小于圆圈范围的半径R,扔一枚硬币,已经硬币的半径r,坐标x,y和速度矢量vx,vy,如果击中印章则被反弹,求硬币在圆圈范围内(有一点就算)的时间,硬币也可能根本不进入圆圈.

思路:首先判断硬币是否进入圆圈,已知方向向量,再加入一条从该点指向圆心的向量,如果两向量夹角为钝角,那么一定没有进入

怎么求夹角:a*b=|a|*|b|*cos(a,b);      a*b=x1*x2+y1*y2;

直角是临界

为什么呢?

想想这个图形:圆形      直角?

那不就是与圆相切吗(此时的这个⚪是以R+r为半径的圆)

圆(R+r)内的还可以思考一下能不能进入R里面,但是圆外的

想都别想!

判断完这个大的范围之后,我们该判断R+r这个圆内的情况了

硬币运动轨迹方程

vy/vx就是斜率k,再带入坐标,就ok了

有了方程,我们可以求出圆心到方程的距离d(自己算去)

根据d判断硬币是否进入圆圈,是否与印章相碰撞

如果d>R+r,那么硬币无法进入圆圈范围

如果d>Rm+r,硬币进入圆圈但没有碰到印章  

如果d<Rm+r,硬币碰到印章

思路就是这样,至于怎么计算~

靠你们了

代码:

#include<cstdio>
#include<cstring>
#include<math.h>
#include<iostream>
#include<iomanip>
#include<map>
#include<set>
#include<queue>
#include<stack>
#include<algorithm>
using namespace std;

#define debug(x) printf("%d***\n",x)
#define ll long long
#define maxn 5005
#define inf 0x3f3f3f3f
const double eps=1e-6;

int main()
{
    double R,Rm,r,x,y,vx,vy;
    while(~scanf("%lf %lf %lf %lf %lf %lf %lf",&Rm,&R,&r,&x,&y,&vx,&vy))
    {
        double d;
        if(vx==0)  //k=无穷大
            d=fabs(x);  //注意取绝对值
        else if(vy==0)  //k=0
            d=fabs(y);
        else  
            d=fabs(y-vy*x/vx)/sqrt((vy/vx)*(vy/vx)+1);
        if(vx*(-x)+vy*(-y)<0) printf("0.000\n");   //另一个向量是(-x,-y);
        else if(d<Rm+r)
            printf("%.3lf\n",2*(sqrt((R+r)*(R+r)-d*d)-sqrt((Rm+r)*(Rm+r)-d*d))/(sqrt(vx*vx+vy*vy)));
        else if(d>=R+r)printf("0.000\n");
        else
            printf("%.3lf\n",(sqrt((R+r)*(R+r)-d*d)*2)/(sqrt(vx*vx+vy*vy)));
    }

    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值