HDU 5572 (平面几何)

来源:互联网 发布:乐高ev3编程软件教育版 编辑:程序博客网 时间:2024/04/29 19:09

题目链接:点击这里

题意: 平面上一个圆, 两个圆外的点A,B, 给A一个初速度, 问能否碰到B.

根据A的运行射线轨迹分成两种情况:
1. 如果运行时不撞到圆, 那么判断B在射线上即可;
2. 如果撞到圆, 求出比较近的那个交点P, 求出A关于OP的对称点A, 那么判断B在线段AP或者射线PA上即可.

trick:因为输入都是整数, 所以精度开的大一点.

#include <cstdio>#include <cmath>#include <algorithm>#include <iostream>#include <vector>using namespace std;#define maxn 100005const double eps = 1e-5;const double INF = 1e20;const double pi = acos (-1.0);int dcmp (double x) {    if (fabs (x) < eps) return 0;    return (x < 0 ? -1 : 1);}inline double sqr (double x) {return x*x;}//*************点struct Point {    double x, y;    Point (double _x = 0, double _y = 0):x(_x), y(_y) {}    void input () {scanf ("%lf%lf", &x, &y);}    void output () {printf ("%.2f %.2f\n", x, y);}    bool operator == (const Point &b) const {        return (dcmp (x-b.x) == 0 && dcmp (y-b.y) == 0);    }    bool operator < (const Point &b) const {        return (dcmp (x-b.x) == 0 ? dcmp (y-b.y) < 0 : x < b.x);    }    Point operator + (const Point &b) const {        return Point (x+b.x, y+b.y);    }    Point operator - (const Point &b) const {        return Point (x-b.x, y-b.y);    }    Point operator * (double a) {        return Point (x*a, y*a);    }    Point operator / (double a) {        return Point (x/a, y/a);    }    double len2 () {//返回长度的平方        return sqr (x) + sqr (y);    }    double len () {//返回长度        return sqrt (len2 ());    }    Point change_len (double r) {//转化为长度为r的向量        double l = len ();        if (dcmp (l) == 0) return *this;//零向量返回自身        r /= l;        return Point (x*r, y*r);    }};double cross (Point a, Point b) {//叉积    return a.x*b.y-a.y*b.x;}double dot (Point a, Point b) {//点积    return a.x*b.x + a.y*b.y;}double dis (Point a, Point b) {//两个点的距离    Point p = b-a; return p.len ();}//************直线 线段struct Line {    Point s, e;//直线的两个点    double k;//极角    Line () {}    Line (Point _s, Point _e) {        s = _s, e = _e;        k = atan2 (e.y - s.y,e.x - s.x);    }    void input () {        s.input ();        e.input ();    }    void adjust () {        if (e < s) swap (e, s);    }    double length () {//求线段长度        return dis (s, e);    }    void get_angle () {        k = atan2 (e.y - s.y,e.x - s.x);    }};int relation (Point p, Line l) {//点和直线的关系    //1:在左侧 2:在右侧 3:在直线上    int c = dcmp (cross (p-l.s, l.e-l.s));    if (c < 0) return 1;    else if (c > 0) return 2;    else return 3;}bool point_on_seg (Point p, Line l) {//判断点在线段上    return dcmp (cross (p-l.s, l.e-l.s)) == 0 &&    dcmp (dot (p-l.s, p-l.e) <= 0);    //如果忽略端点交点改成小于号就好了}bool point_on_halfline (Point p, Line l) {//判断点在射线上    int id = relation (p, l);    if (id != 3) return 0;    return dcmp (dot (p-l.s, l.e-l.s)) >= 0;}double point_to_line (Point p, Line a) {//点到直线的距离    return fabs (cross (p-a.s, a.e-a.s) / a.length ());}Point projection (Point p, Line a) {//点在直线上的投影    return a.s + (((a.e-a.s) * dot (a.e-a.s, p-a.s)) / (a.e-a.s).len2() );}Point symmetry (Point p, Line a) {//点关于直线的对称点    Point q = projection (p, a);    return Point (2*q.x-p.x, 2*q.y-p.y);}//***************圆struct Circle {    //圆心 半径    Point p;    double r;    Circle () {}    Circle (Point _p, double _r) : p(_p), r(_r) {}    Circle (double a, double b, double _r) {        p = Point (a, b);        r = _r;    }    void input () {        p.input ();        scanf ("%lf", &r);    }    void output () {        p.output ();        printf (" %.2f\n", r);    }};int relation (Line a, Circle b) {//直线和圆的关系    //0:相离 1:相切 2:相交    double p = point_to_line (b.p, a);    if (dcmp (p-b.r) == 0) return 1;    return (dcmp (p-b.r) < 0 ? 2 : 0);}int line_circle_intersection (Line v, Circle u, Point &p1, Point &p2) {//直线和圆的交点    //返回交点个数 交点保存在引用中    if (!relation (v, u)) return 0;    Point a = projection (u.p, v);    double d = point_to_line (u.p, v);    d = sqrt (u.r*u.r - d*d);    if (dcmp (d) == 0) {        p1 = a, p2 = a;        return 1;    }    p1 = a + (v.e-v.s).change_len (d);    p2 = a - (v.e-v.s).change_len (d);    return 2;}Circle c;Point a, b, v;Point p1, p2;bool solve () {    Point aa = a+v;    Line pre = Line (a, aa);    int cnt = line_circle_intersection (pre, c, p1, p2);    if (cnt < 2) {        if (point_on_halfline (b, pre))            return 1;        else            return 0;    }    if (dis (p1, a) > dis (p2, a)) p1 = p2;    Line Seg (a, p1);    if (point_on_seg (b, Seg))        return 1;    Line faxian (p1, c.p);    aa = symmetry (a, faxian);    Line now (p1, aa);    if (point_on_halfline (b, now))        return 1;    return 0;}int main () {    int t, kase = 0;    scanf ("%d", &t);    while (t--) {        printf ("Case #%d: ", ++kase);        c.p.input (), scanf ("%lf", &c.r);        a.input (), v.input (), b.input ();        puts (solve () ? "Yes" : "No");    }    return 0;}/*100 1 1-1 0 1 0100000 00 1 1-1 0 1 15 50 1 10 -99 0 123450 -100*/
0 0
原创粉丝点击