• 简单几何(直线与圆的交点) ZOJ Collision 3728


    题目传送门

    题意:有两个一大一小的同心圆,圆心在原点,大圆外有一小圆,其圆心有一个速度(vx, vy),如果碰到了小圆会反弹,问该圆在大圆内运动的时间

    分析:将圆外的小圆看成一个点,判断该直线与同心圆的交点,根据交点个数计算时间。用到了直线的定义,圆的定义,直线与圆交点的个数。

    /************************************************
    * Author        :Running_Time
    * Created Time  :2015/10/24 星期六 16:14:33
    * File Name     :C.cpp
     ************************************************/
    
    #include <cstdio>
    #include <algorithm>
    #include <iostream>
    #include <sstream>
    #include <cstring>
    #include <cmath>
    #include <string>
    #include <vector>
    #include <queue>
    #include <deque>
    #include <stack>
    #include <list>
    #include <map>
    #include <set>
    #include <bitset>
    #include <cstdlib>
    #include <ctime>
    using namespace std;
    
    #define lson l, mid, rt << 1
    #define rson mid + 1, r, rt << 1 | 1
    typedef long long ll;
    const int N = 1e5 + 10;
    const int INF = 0x3f3f3f3f;
    const int MOD = 1e9 + 7;
    const double EPS = 1e-10;
    int dcmp(double x)  {       //三态函数,减少精度问题
        if (fabs (x) < EPS) return 0;
        else    return x < 0 ? -1 : 1;
    }
    struct Point    {       //点的定义
        double x, y;
        Point (double x=0, double y=0) : x (x), y (y) {}
        Point operator + (const Point &r) const {       //向量加法
            return Point (x + r.x, y + r.y);
        }
        Point operator - (const Point &r) const {       //向量减法
            return Point (x - r.x, y - r.y);
        }
        Point operator * (double p)  {       //向量乘以标量
            return Point (x * p, y * p);
        }
        Point operator / (double p)  {       //向量除以标量
            return Point (x / p, y / p);
        }
        bool operator < (const Point &r) const {       //点的坐标排序
            return x < r.x || (x == r.x && y < r.y);
        }
        bool operator == (const Point &r) const {       //判断同一个点
            return dcmp (x - r.x) == 0 && dcmp (y - r.y) == 0;
        }
    };
    typedef Point Vector;       //向量的定义
    Point read_point(void)   {      //点的读入
        double x, y;
        scanf ("%lf%lf", &x, &y);
        return Point (x, y);
    }
    double polar_angle(Vector A)  {     //向量极角
        return atan2 (A.y, A.x);
    }
    double dot(Vector A, Vector B)  {       //向量点积
        return A.x * B.x + A.y * B.y;
    }
    double cross(Vector A, Vector B)    {       //向量叉积
        return A.x * B.y - A.y * B.x;
    }
    double length(Vector A) {       //向量长度,点积
        return sqrt (dot (A, A));
    }
    double angle(Vector A, Vector B)    {       //向量转角,逆时针,点积
        return acos (dot (A, B) / length (A) / length (B));
    }
    double area_triangle(Point a, Point b, Point c) {       //三角形面积,叉积
        return fabs (cross (b - a, c - a)) / 2.0;
    }
    Vector rotate(Vector A, double rad) {       //向量旋转,逆时针
        return Vector (A.x * cos (rad) - A.y * sin (rad), A.x * sin (rad) + A.y * cos (rad));
    }
    Vector nomal(Vector A)  {       //向量的单位法向量
        double len = length (A);
        return Vector (-A.y / len, A.x / len);
    }
    Point point_inter(Point p, Vector V, Point q, Vector W)    {        //两直线交点,参数方程
        Vector U = p - q;
        double t = cross (W, U) / cross (V, W);
        return p + V * t;
    }
    double dis_to_line(Point p, Point a, Point b)   {       //点到直线的距离,两点式
        Vector V1 = b - a, V2 = p - a;
        return fabs (cross (V1, V2)) / length (V1);
    }
    double dis_to_seg(Point p, Point a, Point b)    {       //点到线段的距离,两点式
      
        if (a == b) return length (p - a);
        Vector V1 = b - a, V2 = p - a, V3 = p - b;
        if (dcmp (dot (V1, V2)) < 0)    return length (V2);
        else if (dcmp (dot (V1, V3)) > 0)   return length (V3);
        else    return fabs (cross (V1, V2)) / length (V1);
    }
    Point point_proj(Point p, Point a, Point b)   {     //点在直线上的投影,两点式
        Vector V = b - a;
        return a + V * (dot (V, p - a) / dot (V, V));
    }
    bool inter(Point a1, Point a2, Point b1, Point b2)  {       //判断线段相交,两点式
        double c1 = cross (a2 - a1, b1 - a1), c2 = cross (a2 - a1, b2 - a1),
               c3 = cross (b2 - b1, a1 - b1), c4 = cross (b2 - b1, a2 - b1);
        return dcmp (c1) * dcmp (c2) < 0 && dcmp (c3) * dcmp (c4) < 0;
    }
    bool on_seg(Point p, Point a1, Point a2)    {       //判断点在线段上,两点式
        return dcmp (cross (a1 - p, a2 - p)) == 0 && dcmp (dot (a1 - p, a2 - p)) < 0;
    }
    double area_poly(Point *p, int n)   {       //多边形面积
        double ret = 0;
        for (int i=1; i<n-1; ++i)   {
            ret += fabs (cross (p[i] - p[0], p[i+1] - p[0]));
        }
        return ret / 2;
    }
    /*
        点集凸包,输入点集会被修改
    */
    vector<Point> convex_hull(vector<Point> &P) {
        sort (P.begin (), P.end ());
        P.erase (unique (P.begin (), P.end ()), P.end ());      //预处理,删除重复点
        int n = P.size (), m = 0;
        vector<Point> ret (n + 1);
        for (int i=0; i<n; ++i) {
            while (m > 1 && cross (ret[m-1]-ret[m-2], P[i]-ret[m-2]) < 0)   m--;
            ret[m++] = P[i];
        }
        int k = m;
        for (int i=n-2; i>=0; --i)  {
            while (m > k && cross (ret[m-1]-ret[m-2], P[i]-ret[m-2]) < 0)   m--;
            ret[m++] = P[i];
        }
        if (n > 1)  m--;
        ret.resize (m);
        return ret;
    }
     
    struct Circle   {
        Point c;
        double r;
        Circle () {}
        Circle (Point c, double r) : c (c), r (r) {}
        Point point(double a)   {
            return Point (c.x + cos (a) * r, c.y + sin (a) * r);
        }
    };
    
    struct Line {
        Point p;
        Vector v;
        double r;
        Line () {}
        Line (const Point &p, const Vector &v) : p (p), v (v) {
            r = polar_angle (v);
        }
        Point point(double a)   {
            return p + v * a;
        }
    };
    
    
    /*
        直线相交求交点,返回交点个数,交点保存在P中
    */
    int line_cir_inter(Line L, Circle C, double &t1, double &t2, vector<Point> &P)    {
        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 = a * a + c * c, f = 2 * (a * b + c * d), g = b * b + d * d - C.r * C.r;
        double delta = f * f - 4 * e * g;
        if (dcmp (delta) < 0)   return 0;
        if (dcmp (delta) == 0)  {
            t1 = t2 = -f / (2 * e); P.push_back (L.point (t1));
            return -1;
        }
        t1 = (-f - sqrt (delta)) / (2 * e); P.push_back (L.point (t1));
        t2 = (-f + sqrt (delta)) / (2 * e); P.push_back (L.point (t2));
        if (dcmp (t1) < 0 || dcmp (t2) < 0) return 0;
        return 2;
    }
     
    /*
        两圆相交求交点,返回交点个数。交点保存在P中
    */
    int cir_cir_inter(Circle C1, Circle C2, vector<Point> &P)    {
        double d = length (C1.c - C2.c);
        if (dcmp (d) == 0)  {
            if (dcmp (C1.r - C2.r) == 0)    return -1;      //两圆重叠
            else    return 0;
        }
        if (dcmp (C1.r + C2.r - d) < 0) return 0;
        if (dcmp (fabs (C1.r - C2.r) - d) < 0)  return 0;
        double a = polar_angle (C2.c - C1.c);
        double da = acos ((C1.r * C1.r + d * d - C2.r * C2.r) / (2 * C1.r * d));        //C1C2到C1P1的角?
        Point p1 = C1.point (a - da), p2 = C2.point (a + da);
        P.push_back (p1);
        if (p1 == p2)   return 1;
        else    P.push_back (p2);
        return 2;
    }
    
    int main(void)    {
        Circle C1, C2;  Point a, b;
        double Rm, R, r, x, y, vx, vy;
        while (scanf ("%lf%lf%lf%lf%lf%lf%lf", &Rm, &R, &r, &x, &y, &vx, &vy) == 7)    {
            Rm += r;    R += r;
            C1 = Circle (Point (0, 0), Rm);
            C2 = Circle (Point (0, 0), R);
            a = Point (x, y);   b = Point (vx, vy);
            vector<Point> P1, P2;   P1.clear ();    P2.clear ();
            double t1, t2, t3, t4, ans, speed = sqrt (vx * vx + vy * vy);
            int num1 = line_cir_inter (Line (a, b), C1, t1, t2, P1);
            int num2 = line_cir_inter (Line (a, b), C2, t3, t4, P2);
            if (num2 == 2)  {
                if (num1 == 2)   {
                    double len = length (P2[0] - P2[1]) - length (P1[0] - P1[1]);
                    ans = len / speed;
                }
                else    {
                    ans = length (P2[0] - P2[1]) / speed;
                }
            }
            else    {
                ans = 0.0;
            }
            printf ("%.4f
    ", ans);
        }
    
        return 0;
    }
    

      

    编译人生,运行世界!
  • 相关阅读:
    scrapy中selenium的应用
    Django的锁和事务
    redis
    【leetcode】187. Repeated DNA Sequences
    【leetcode】688. Knight Probability in Chessboard
    【leetcode】576. Out of Boundary Paths
    【leetcode】947. Most Stones Removed with Same Row or Column
    【leetcode】948. Bag of Tokens
    【leetcode】946. Validate Stack Sequences
    【leetcode】945. Minimum Increment to Make Array Unique
  • 原文地址:https://www.cnblogs.com/Running-Time/p/4907417.html
Copyright © 2020-2023  润新知