HDU 5572 An Easy Physics Problem (计算几何)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/GYH0730/article/details/82388501

An Easy Physics Problem

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 3631    Accepted Submission(s): 721


Problem Description

On an infinite smooth table, there's a big round fixed cylinder and a little ball whose volume can be ignored.

Currently the ball stands still at point A, then we'll give it an initial speed and a direction. If the ball hits the cylinder, it will bounce back with no energy losses.

We're just curious about whether the ball will pass point B after some time.

Input

First line contains an integer T, which indicates the number of test cases.

Every test case contains three lines.

The first line contains three integers Ox, Oy and r, indicating the center of cylinder is (Ox,Oy) and its radius is r.

The second line contains four integers Ax, Ay, Vx and Vy, indicating the coordinate of A is (Ax,Ay) and the initial direction vector is (Vx,Vy).

The last line contains two integers Bx and By, indicating the coordinate of point B is (Bx,By).

⋅ 1 ≤ T ≤ 100.

⋅ |Ox|,|Oy|≤ 1000.

⋅ 1 ≤ r ≤ 100.

⋅ |Ax|,|Ay|,|Bx|,|By|≤ 1000.

⋅ |Vx|,|Vy|≤ 1000.

Vx≠0 or Vy≠0.

⋅ both A and B are outside of the cylinder and they are not at same position.

Output

For every test case, you should output "Case #x: y", where x indicates the case number and counts from 1. y is "Yes" if the ball will pass point B after some time, otherwise y is "No".

Sample Input

2 0 0 1 2 2 0 1 -1 -1 0 0 1 -1 2 1 -1 1 2

Sample Output

Case #1: No Case #2: Yes

计算几何的题还是写的少,调了一个小时的蜜汁bug最后发现被卡精度了,得用long double,这题思路上并不难,先判断一下直线AV是否与圆的交点个数,如果少于2个交点,判断B是否在射线AV上,如果有两个交点,求出距离A较近的那个交点P1,求出A关于QP1的对称点A1,判断B是否在线段AP1上或是否在射线P1A1上

用的都是kuangbin最新的板子

#include <bits/stdc++.h>
using namespace std;
typedef long double LD;
const LD eps = 1e-8;
const double pi = acos(-1.0);
int sgn(LD x)
{
    if(fabs(x) < eps) return 0;
    if(x < 0) return -1;
    else return 1;
}
struct Point
{
    LD x,y;
    Point(){}
    Point(LD _x,LD _y)
    {
        x = _x;
        y = _y;
    }
    bool operator == (Point b) const
    {
        return sgn(x - b.x) == 0 && sgn(y - b.y) == 0;
    }
    bool operator < (Point b) const
    {
        return sgn(x - b.x) == 0 ? sgn(y - b.y) < 0 : x < b.x;
    }
    Point operator -(const Point &b) const
    {
        return Point(x - b.x,y - b.y);
    }
    LD operator ^(const Point &b) const
    {
        return x * b.y - y * b.x;
    }
    LD operator *(const Point &b)const
    {
        return x * b.x + y * b.y;
    }
    LD len()
    {
        return hypot(x,y);
    }
    LD len2()
    {
        return x * x + y * y;
    }
    LD distance(Point p)
    {
        return hypot(x - p.x,y - p.y);
    }
    Point operator +(const Point &b) const
    {
        return Point(x + b.x,y + b.y);
    }
    Point operator *(const double &k) const
    {
        return Point(x * k,y * k);
    }
    Point operator /(const double &k)const
    {
        return Point(x / k,y / k);
    }
    Point trunc(LD r)
    {
        LD l = len();
        if(!sgn(l)) return *this;
        r /= l;
        return Point(x * r,y * r);
    }
};
struct Line
{
     Point s,e;
     Line(){}
     Line(Point _s,Point _e)
     {
         s = _s;
         e = _e;
     }
     LD length()
     {
        return s.distance(e);
     }
     int relation(Point p)
     {
        int c = sgn((p - s) ^ (e - s));
        if(c < 0)return 1;
        else if(c > 0)return 2;
        else return 3;
     }
     LD dispointtoline(Point p)
     {
        return fabs((p - s) ^ (e - s)) / length();
     }
     Point lineprog(Point p)
     {
        return s + ( ((e - s) * ((e - s)*(p -s))) / ((e - s).len2()) );
     }
     Point symmetrypoint(Point p)
     {
        Point q = lineprog(p);
        return Point(2 * q.x - p.x,2 * q.y - p.y);
     }
     bool pointonseg(Point p)
     {
        return sgn((p - s)^(e - s)) == 0 && sgn((p - s)*(p - e)) <= 0;
     }
};
struct Circle
{
     Point p;
     LD r;
     Circle(){}
     Circle(Point _p,LD _r)
     {
        p = _p;
        r = _r;
     }
     Circle(LD x,LD y,LD _r)
     {
        p = Point(x,y);
        r = _r;
     }
     int relation(Point b)
     {
        LD dst = b.distance(p);
        if(sgn(dst - r) < 0)return 2;
        else if(sgn(dst - r)==0)return 1;
        return 0;
     }
     int relationline(Line v)
     {
        LD dst = v.dispointtoline(p);
        if(sgn(dst - r) < 0) return 2;
        else if(sgn(dst - r) == 0) return 1;
        return 0;
     }
     int pointcrossline(Line v,Point &p1,Point &p2)
     {
         if(!(*this).relationline(v))return 0;
         Point a = v.lineprog(p);
         double d = v.dispointtoline(p);
         d = sqrt(r * r - d * d);
         if(sgn(d) == 0){
            p1 = a;
            p2 = a;
            return 1;
         }
         p1 = a + (v.e - v.s).trunc(d);
         p2 = a - (v.e - v.s).trunc(d);
         return 2;
     }
};
int main(void)
{
    LD Qx,Qy,r,Ax,Ay,Vx,Vy,Bx,By;
    int T,kase;
    kase = 0;
    scanf("%d",&T);
    while(T--) {
        kase++;
        cin >> Qx >> Qy >> r >> Ax >> Ay >> Vx >> Vy >> Bx >> By;
        Point Q = Point(Qx,Qy);
        Point A = Point(Ax,Ay);
        Point B = Point(Bx,By);
        Point V = Point(Ax + Vx,Ay + Vy);
        Line LA = Line(A,V);
        Circle O = Circle(Q,r);
        Point P1,P2;
        int cnt = O.pointcrossline(LA,P1,P2);
        if(cnt == 0 || cnt == 1) {
            if(LA.relation(B) == 3 && sgn((V - A) * (B - A)) > 0) printf("Case #%d: Yes\n",kase);
            else printf("Case #%d: No\n",kase);
        }
        else {
            if(sgn(A.distance(P1) - A.distance(P2)) > 0) P1 = P2;
            Line QP1 = Line(Q,P1);
            Line AP1 = Line(A,P1);
            Point A1 = QP1.symmetrypoint(A);
            Line P1A1 = Line(P1,A1);
            if(AP1.pointonseg(B)) printf("Case #%d: Yes\n",kase);
            else if(P1A1.relation(B) == 3 && sgn((A1 - P1) * (B - P1)) > 0) printf("Case #%d: Yes\n",kase);
            else printf("Case #%d: No\n",kase);
        }
    }
    return 0;
}
/*
*/

猜你喜欢

转载自blog.csdn.net/GYH0730/article/details/82388501