HDU 5572--An Easy Physics Problem(射线和圆的交点) An Easy Physics Problem Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 3845    Accepted Submission(s): 768

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

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 B after some time.
 
Input
First line contains an integer ).

 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 
 
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
 
先判断射线和圆交点个数,如果小于2再看是否B在A的前进方向上,没有则NO,否则YES。如果等于2,就先找到第一个交点,将这个交点和圆心连成直线,那么A的路径关于这条直线对称,那么如果A关于此直线的对称点在圆心->B路径上,则可以相撞,否则不行。
这里有一个小问题,如果反过来求B关于此直线的对称点在圆心->A路径上,是会WA的.
 
  1 #include <iostream>
  2 #include <cstdio>
  3 #include <cstring>
  4 #include<algorithm>
  5 #include <cstdlib>
  6 #include <cmath>
  7 using namespace std;
  8 const double eps = 1e-8;
  9 int sgn(double x) {
 10     if (fabs(x) < eps)return 0;
 11     if (x < 0)return -1;
 12     else return 1;
 13 }
 14 struct point {
 15     double x, y;
 16     point() {}
 17     point(double x, double y) : x(x), y(y) {}
 18     void input() {
 19         scanf("%lf%lf", &x, &y);
 20     }
 21     bool operator ==(point b)const {
 22         return sgn(x - b.x) == 0 && sgn(y - b.y) == 0;
 23     }
 24     bool operator <(point b)const {
 25         return sgn(x - b.x) == 0 ? sgn(y - b.y)<0 : x<b.x;
 26     }
 27     point operator -(const point &b)const {        //返回减去后的新点
 28         return point(x - b.x, y - b.y);
 29     }
 30     point operator +(const point &b)const {        //返回加上后的新点
 31         return point(x + b.x, y + b.y);
 32     }
 33     point operator *(const double &k)const {    //返回相乘后的新点
 34         return point(x * k, y * k);
 35     }
 36     point operator /(const double &k)const {    //返回相除后的新点
 37         return point(x / k, y / k);
 38     }
 39     double operator ^(const point &b)const {    //叉乘
 40         return x*b.y - y*b.x;
 41     }
 42     double operator *(const point &b)const {    //点乘
 43         return x*b.x + y*b.y;
 44     }
 45     double len() {        //返回长度
 46         return hypot(x, y);
 47     }
 48     double len2() {        //返回长度的平方
 49         return x*x + y*y;
 50     }
 51     point trunc(double r) {
 52         double l = len();
 53         if (!sgn(l))return *this;
 54         r /= l;
 55         return point(x*r, y*r);
 56     }
 57 };
 58 struct line {
 59     point s;
 60     point e;
 61     line() {
 62 
 63     }
 64     line(point _s, point _e) {
 65         s = _s;
 66         e = _e;
 67     }
 68     bool operator ==(line v) {
 69         return (s == v.s) && (e == v.e);
 70     }
 71     //返回点p在直线上的投影
 72     point lineprog(point p) {
 73         return s + (((e - s)*((e - s)*(p - s))) / ((e - s).len2()));
 74     }
 75     //返回点p关于直线的对称点
 76     point symmetrypoint(point p) {
 77         point q = lineprog(p);
 78         return point(2 * q.x - p.x, 2 * q.y - p.y);
 79     }
 80     //点是否在线段上
 81     bool pointonseg(point p) {
 82         return sgn((p - s) ^ (e - s)) == 0 && sgn((p - s)*(p - e)) <= 0;
 83     }
 84 };
 85 struct circle {//
 86     double r;    //半径
 87     point p;    //圆心
 88     void input() {
 89         p.input();
 90         scanf("%lf", &r);
 91     }
 92     circle() { }
 93     circle(point _p, double _r) {
 94         p = _p;
 95         r = _r;
 96     }
 97     circle(double x, double y, double _r) {
 98         p = point(x, y);
 99         r = _r;
100     }
101     //求直线和圆的交点,返回交点个数
102     int pointcrossline(line l, point &r1, point &r2) {
103         double dx = l.e.x - l.s.x, dy = l.e.y - l.s.y;
104         double A = dx*dx + dy*dy;
105         double B = 2 * dx * (l.s.x - p.x) + 2 * dy * (l.s.y - p.y);
106         double C = (l.s.x - p.x)*(l.s.x - p.x) + (l.s.y - p.y)*(l.s.y - p.y) - r*r;
107         double del = B*B - 4 * A * C;
108         if (sgn(del) < 0)  return 0;
109         int cnt = 0;
110         double t1 = (-B - sqrt(del)) / (2 * A);
111         double t2 = (-B + sqrt(del)) / (2 * A);
112         if (sgn(t1) >= 0) {
113             r1 = point(l.s.x + t1 * dx, l.s.y + t1 * dy);
114             cnt++;
115         }
116         if (sgn(t2) >= 0) {
117             r2 = point(l.s.x + t2 * dx, l.s.y + t2 * dy);
118             cnt++;
119         }
120         return cnt;
121     }
122 };
123 point A, V, B;
124 circle tc;
125 point r1, r2;
126 int main() {
127     int t, d = 1;
128     scanf("%d", &t);
129     while (t--) {
130         tc.input();
131         A.input();
132         V.input();
133         B.input();
134         int f = 0;
135         int num = tc.pointcrossline(line(A, A + V), r1, r2);
136         if (num < 2) {
137             point t = B - A;
138             if (t.trunc(1) == V.trunc(1)) f = 1;
139             else f = 0;
140         }
141         else {
142             line l = line(tc.p, r1);
143             line l1 = line(A, r1);
144             line l2 = line(r1, B);
145             point t = l.symmetrypoint(A);
146             if (l1.pointonseg(B))f = 1;
147             else if (l2.pointonseg(t))f = 1;        //求B的对称点会WA
148             else f = 0;
149         }
150         if (f == 1)
151             printf("Case #%d: Yes
", d++);
152         else
153             printf("Case #%d: No
", d++);
154     }
155     return 0;
156 }
View Code