天天看點

HDU 4793 Collision --解方程

題意: 給一個圓盤,圓心為(0,0),半徑為Rm, 然後給一個圓形區域,圓心同此圓盤,半徑為R(R>Rm),一枚硬币(圓形),圓心為(x,y),半徑為r,一定在圓形區域外面,速度向量為(vx,vy),硬币向圓盤撞過去,碰到圓盤後會以相反方向相同速度回來(好像有點違背實體規律啊,但是題目是這樣,沒辦法)。問硬币某一部分在圓形區域内的總時間。

解法: 解方程,求 (x+vx*t,y+vy*t) 代入圓形區域方程是否有解,如果沒解,說明硬币運動軌迹與圓形區域都不相交,答案為0

如果有解,再看代入圓盤有沒有解,如果有解,即為兩個解的內插補點*2, 如果沒解,那麼就是與圓形區域相交的兩個點的t的內插補點。

有一個坑就是t的解可能為負,要判掉。

代碼:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <algorithm>
#define eps 1e-8
using namespace std;
#define N 10007

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)!=EOF)
    {
        double A1 = (vx*vx+vy*vy);
        double B1 = (2*vx*x+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 delta1 = B1*B1 - 4.0*A1*C1;
        double delta2 = B2*B2 - 4.0*A2*C2;
        if(sgn(delta1) <= 0)
        {
            puts("0.000");
            continue;
        }
        double J11 = (-B1 + sqrt(delta1))/(2.0*A1);
        double J12 = (-B1 - sqrt(delta1))/(2.0*A1);
        if(sgn(J12) >= 0)
        {
            if(sgn(delta2) <= 0)
            {
                printf("%.3f\n",fabs(J11-J12));
                continue;
            }
            double J22 = (-B2 - sqrt(delta2))/(2.0*A2);
            printf("%.3f\n",(J22-J12)*2.0);
        }
        else
            puts("0.000");
    }
    return 0;
}      

View Code

轉載于:https://www.cnblogs.com/whatbeg/p/4080167.html