An Easy Physics Problem

41 篇文章 0 订阅
16 篇文章 0 订阅

An Easy Physics Problem

这里写图片描述
.
.
题意:平面上一个点与圆,点延一个方向前进,问能否达到另外一个点。
.
.
解法:分两种,1是相撞,2是相离或相切。对于第二种直接求解就好了,而第一种注意一下精度,考虑点出现在相撞前的地方等就好了。
.
.
队友代码

#include <cstdio>
#include <iostream>
#include <cmath>
#include <vector>

using namespace std;

const double eps=1e-6;
typedef long long LL;

int dcmp(double x) {
    if (fabs(x)<eps) return 0;
    else if (x<0) return -1;
    else return 1;
}

struct Point {
    double x, y;
    Point() {}
    Point(double x, double y): x(x), y(y) {}
    void read() {scanf("%lf%lf", &x, &y);}
    Point operator+ (const Point& a) {
        return Point(x+a.x, y+a.y);
    }
    Point operator- (const Point& a) {
        return Point(x-a.x, y-a.y);
    }
} a, v, b;

Point operator*(double t, Point a) {
    return Point(t*a.x, t*a.y);
}
struct Line {
    Point p, v;
    Line() {}
    Line(Point p, Point v): p(p.x, p.y), v(v.x, v.y) {}
    Point point(double t) {
        return p+(t*v);
    }
};
struct Circle {
    Point c;
    double r;
    void read() {c.read(); scanf("%lf", &r);}
} cc;

inline double sqr(double x) {return x*x;}
int getLineCircleIntersection(Line L, Circle C, Point& sol) {
    double t;
    double a=L.v.x, b=L.p.x-C.c.x, c=L.v.y, d=L.p.y-C.c.y;
    double e=sqr(a)+sqr(c), f=2*(a*b+c*d), g=sqr(b)+sqr(d)-sqr(C.r);
    double delta=f*f-4*e*g;
    if (dcmp(delta)<=0) return 0;
    else {
        t=(-f-sqrt(delta))/(2*e);
        if (dcmp(t)>0) {
            sol=L.point(t);
            return 1;
        }
        else return 0;
    }
}

bool det(Point a, Point b) {
    return fabs(a.x*b.y-a.y*b.x)<eps;
}

bool SameLine(Point v, Point p) {
    double a=v.x, b=v.y, c=p.x, d=p.y;
        int aa=dcmp(a), bb=dcmp(b);
        int cc=dcmp(c), dd=dcmp(d);
        if (aa*cc>=0&&bb*dd>=0&&det(v, p)) return true;
        else return false;
}

double dist(Point a, Point b) {
    return hypot(a.x-b.x, a.y-b.y);
}
double Dot(Point a, Point b) {
    return a.x*b.x+a.y*b.y;
}
Point GetLineProjection(Point P, Point A, Point B) {
    Point v=B-A;
    return A+(Dot(v, P-A)/Dot(v, v))*v;
}

int main() {
    // freopen("untitled.in", "r", stdin);
    int T, kase=0; cin >> T;
    while (T--) {
        printf("Case #%d: ", ++kase);
        cc.read(); a.read(); v.read(); b.read();
        Line l(a, v);
        Point i;
        bool flag=getLineCircleIntersection(l, cc, i);
        if (flag) {
            if (SameLine(v, b-a)&&dist(a, b)<dist(a, i)+eps) puts("Yes");
            else {
                Point bb=GetLineProjection(b, i, cc.c);
                b=2*bb-b;
                if (SameLine(Point(-v.x, -v.y), b-i)) puts("Yes");
                else puts("No");
            }
        }
        else {
            if (SameLine(v, b-a)) puts("Yes");
            else puts("No");
        }
    }
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值