sgu283:Mechanics(計算幾何)

題目大意:
       給你平面上兩個圓(x1,y1),(x2,y2) ,以及它們的質量m1,m2 和速度v1,v2
       碰撞過程中不考慮能量損失。
       求出在時刻t 的兩圓座標和速度。

分析:
       首先我們很容易解個方程求出碰撞時間。問題就是如何計算碰撞後的速度。
       設碰撞時兩圓圓心爲A,B ,將v1,v2 根據AB 正交分解爲垂直的law1,law2 ,和共線的x,y ,即v1=law1+x,v2=law2+y 。那麼根據動量守恆和能量守恆,碰撞後只有x,y 會改變,我們可以列出兩個方程:
                      {m1x+m2y=m1x+m2ym1v21+m2v22=m1(law21+x2)+m2(law22+y2)
       解出來就是x=((m1m21)x+2y)/(1+m1m2),y=x+xy
       然後就沒有然後了...

AC code:

#include <cstdio>
#include <cmath>
#include <algorithm>
#define sqr(x) ((x)*(x))
typedef double DB;
using namespace std;

const DB eps = 1e-9;

struct pot
{
    DB x, y;
    pot() {x = y = 0;}
    pot(DB _x, DB _y):x(_x),y(_y){}
    void read() {scanf("%lf%lf", &x, &y);}
    void print() {printf("%.3lf %.3lf", x, y);}

    friend pot operator + (const pot &a, const pot &b) {return pot(a.x+b.x, a.y+b.y);}
    friend pot operator - (const pot &a, const pot &b) {return pot(a.x-b.x, a.y-b.y);}
    friend pot operator * (const pot &a, DB k) {return pot(a.x*k, a.y*k);}
    friend pot operator / (const pot &a, DB k) {return pot(a.x/k, a.y/k);}
    friend DB operator * (const pot &a, const pot &b) {return a.x*b.x+a.y*b.y;}
    friend DB operator ^ (const pot &a, const pot &b) {return a.x*b.y-a.y*b.x;}
    DB size() {return sqrt(sqr(x)+sqr(y));}

}p1, v1, p2, v2;
DB r1, r2, m1, m2, t;
DB bump_t;

int sign(DB x)
{
    if(x < -eps) return -1;
    else return x > eps;
}

bool bump()
{
    DB a, b, c, d, e;
    DB A, B, C;
    a = p1.x-p2.x, b = v1.x-v2.x;
    c = p1.y-p2.y, d = v1.y-v2.y;e = r1+r2;
    A = sqr(b)+sqr(d), B = 2*(a*b+c*d), C = sqr(a)+sqr(c)-sqr(e);
    if(sign(A) == 0)
    {
        if(sign(-C/B) < 0) return false;
        else 
        {
            bump_t = -C/B;
            return true;
        }
    } 
    else if(sign(sqr(B)-4*A*C) <= 0) return false;
    else
    {
        DB u, v;
        u = -B/(2*A), v = sqrt(sqr(B)-4*A*C)/(2*A);
        if(sign(u+v) < 0) return false;
        else if(sign(u-v) < 0) bump_t = u+v;
        else bump_t = u-v;
        return true;
    }
}

void solve2(DB t)
{
    p1 = p1+v1*t;
    p2 = p2+v2*t;
    p1.print(), putchar(' '), v1.print(), puts("");
    p2.print(), putchar(' '), v2.print(), puts("");
}

void solve1(DB t)
{
    pot A, B, par, x, y, _x, _y;
    pot law1, law2, _v1, _v2;
    A = p1+v1*bump_t, B = p2+v2*bump_t, par = B-A;
    x = par*(v1*par/sqr(par.size())), y = par*(v2*par/sqr(par.size()));
    law1 = v1-x, law2 = v2-y;
    _x = (x*(m1/m2-1)+y*2)/(1+m1/m2), _y = x+_x-y;
    _v1 = law1+_x, _v2 = law2+_y;
    p1 = A, p2 = B, v1 = _v1, v2 = _v2;
    solve2(t-bump_t);
}

int main()
{
    #ifndef ONLINE_JUDGE
    freopen("input.txt", "r", stdin);
    freopen("output.txt", "w", stdout);
    #endif

    p1.read(), v1.read(), scanf("%lf%lf", &r1, &m1);
    p2.read(), v2.read(), scanf("%lf%lf", &r2, &m2);
    scanf("%lf", &t);
    if(bump())
    {
        if(sign(t-bump_t) > 0)
            solve1(t);
        else solve2(t);
    }
    else solve2(t);

    #ifndef ONLINE_JUDGE
    fclose(stdin);
    fclose(stdout);
    #endif
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章