An Easy Physics Problem HDU - 5572(直线与圆的关系)

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

这个题直接自闭到结尾

定义p1_1(为p1的方向点)首先判断p1_1与p1的直线与圆的交点如果交点个数小于等于2个只要判断p2点与p1到p1_1的方向向量同向(判断方法为叉积为0说明平行点积大于0说明同向)

当直线与圆交点的个数为2时,这时候情况比较特殊,p3_1为与圆的交点离p1最近的点,情况1:p1的方向刚好是往圆那个方向上走去,并且p2点刚好在p1与p3_1这条线段上这时候肯定能碰到!!,

情况2:p3_1与p1与p2三点共线,这时候分类讨论,如果p1的方向是离开圆的而p2的点比p1的点距离圆更近这时候也不可能碰见,否则是一定可以碰见的因为如果p1往圆上走会反弹回来

情况3:过p3_1与圆心o的直线做p1的对称点判断对称点与p2是否共线

#include <iostream>
#include <cmath>
#include <cstdio>
#include <algorithm>

using namespace std;

typedef  double ld;
const ld eps=1e-8;
const ld 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;
    }
    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 distance(Point p){
        return hypot(x - p.x,y - p.y);
    }
    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;
    }
    Point operator *(const ld &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);
    }
    Point operator +(const Point &b)const{
        return Point(x+b.x,y+b.y);
    }
    Point operator /(const ld &k)const{
        return Point(x/k,y/k);
    }
};

struct Line{
    Point s,e;
    Line(){}
    Line(Point _s,Point _e)
    {
        s=_s;
        e=_e;
    }
    ld length(){
        return s.distance(e);
    }
    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()) );
    }
    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;
    }
    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;
    }
    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);
        ld 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()
{
    int t;
    cin>>t;
    int kace=1;
    while(t--)
    {
        ld ox,oy,r,ax,ay,vx,vy,bx,by;
        cin>>ox>>oy>>r;
        cin>>ax>>ay>>vx>>vy;
        cin>>bx>>by;
        Point p1=Point(ax,ay);
        Point p2=Point(bx,by);
        Point o=Point(ox,oy);
        Point p1_1=Point((ax+vx),(ay+vy));
        Line line1=Line(p1,p1_1);
        circle cir=circle(o,r);
        Point p3_1,p3_2;
        int k=cir.pointcrossline(line1,p3_1,p3_2);
        if(k<=1)
        {
            if(line1.relation(p2)==3)
            {
                ld cc1=(p1_1-p1)*(p2-p1);
                if(sgn(cc1)>0)
                    printf("Case #%d: Yes\n",kace++);
                else
                    printf("Case #%d: No\n",kace++);
            }
            else printf("Case #%d: No\n",kace++);
        }
        else
        {
            ld a1=p1.distance(p3_1);
            ld a2=p1.distance(p3_2);
            if(a1>a2)
                swap(p3_1,p3_2);
            Line line2=Line(p3_1,o);
            Point pp1=line2.symmetrypoint(p1);
            ld ans=(pp1-p3_1)^(p2-p3_1);
            Line op1=Line(o,p3_1);
            Line ap1=Line(p1,p3_1);
            if(ap1.pointonseg(p2)&&sgn((p2-p1)*(p3_1-p1))>0)
            {
                printf("Case #%d: Yes\n",kace++);
                continue;
            }
            Line line3=Line(p3_1,pp1);
            if(line3.relation(p2)==3)
            {
                if(((p1-o)^(p2-o))==0)
                {
                    ld att2=(o-p1)*(p1_1-p1);
                    if(sgn(att2)<0)
                    {
                        if(sgn(p2.distance(o)-p1.distance(o))<0)
                            printf("Case #%d: No\n",kace++);
                        else
                            printf("Case #%d: Yes\n",kace++);
                    }
                    else
                        printf("Case #%d: Yes\n",kace++);                   
                }
                else 
                    printf("Case #%d: Yes\n",kace++);

            }
            else printf("Case #%d: No\n",kace++);
        }
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/leekerian/article/details/88982597