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

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

先判断射线和圆交点个数,如果小于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\n", d++);
152         else
153             printf("Case #%d: No\n", d++);
154     }
155     return 0;
156 }

原文地址:https://www.cnblogs.com/FlyerBird/p/9741139.html

时间: 2024-08-08 11:23:38

HDU 5572--An Easy Physics Problem(射线和圆的交点)的相关文章

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): 1430    Accepted Submission(s): 270 Problem Description On an infinite smooth table, there's a big round fixed cylinder an

ACM 2015年上海区域赛A题 HDU 5572An Easy Physics Problem

题意: 光滑平面,一个刚性小球,一个固定的刚性圆柱体 ,给定圆柱体圆心坐标,半径 ,小球起点坐标,起始运动方向(向量) ,终点坐标 ,问能否到达终点,小球运动中如果碰到圆柱体会反射. 学到了向量模板,写法简洁. 1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #include<iostream> 5 #define clc(a,b) sizeof(a,b,sizeof(a)) 6

杭电OJ(HDU)-ACMSteps-Chapter Two-《An Easy Task》《Buildings》《decimal system》《Vowel Counting》

http://acm.hdu.edu.cn/game/entry/problem/list.php?chapterid=1§ionid=2 1.2.5 #include<stdio.h> /* 题意:找闰年. if((i%4==0 && i%100!=0) || i%400==0)count++; 3 2005 25 1855 12 2004 10000 2108 1904 43236 */ int main() { int t,y,n; int i,count=0; whil

hdu 5323 Solve this interesting problem(dfs)

题目链接:hdu 5323 Solve this interesting problem 逆向思维,每次向左或向右翻倍,知道左端点为0时,即恰好满足的情况,处理处所有情况去取最小值. #include <cstdio> #include <cstring> #include <algorithm> using namespace std; typedef long long ll; const ll inf = 0x3f3f3f3f; ll L, R, N; void

hdu 4974 A simple water problem(数学题)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4974 Problem Description Dragon is watching competitions on TV. Every competition is held between two competitors, and surely Dragon's favorite. After each competition he will give a score of either 0 or

HDU 5618:Jam&#39;s problem again(CDQ分治+树状数组处理三维偏序)

http://acm.hdu.edu.cn/showproblem.php?pid=5618 题意:-- 思路:和NEUOJ那题一样的.重新写了遍理解了一下,算作处理三维偏序的模板了. 1 #include <cstdio> 2 #include <algorithm> 3 #include <iostream> 4 #include <cstring> 5 using namespace std; 6 #define INF 0x3f3f3f3f 7 #d

hdu 5349 MZL&#39;s simple problem

Problem Description A simple problem Problem Description You have a multiple set,and now there are three kinds of operations: 1 x : add number x to set 2 : delete the minimum number (if the set is empty now,then ignore it) 3 : query the maximum numbe

【multiset】hdu 5349 MZL&#39;s simple problem

[multiset]hdu 5349 MZL's simple problem 题目链接:hdu 5349 MZL's simple problem 题目大意 n次操作,插入元素.删除最小元素.查询最大元素并输出. C++STL的multiset的使用 set--多元集合(元素不可重复),multiset--可重复元素的多元集合 多元集合(MultiSets)和集合(Sets)相像,只不过支持重复对象.(具体用法请参照set容器) set和multiset内部是以平衡二叉树实现的: 从内部数据结

hdu 5170 GTY&#39;s math problem(水,,数学,,)

题意: 给a,b,c,d. 比较a^b和c^d的大小 思路: 比较log(a^b)和log(c^d)的大小 代码: int a,b,c,d; int main(){ while(scanf("%d%d%d%d",&a,&b,&c,&d)!=EOF){ double x1 = b*log((double)a); double x2 = d*log((double)c); if(fabs(x1-x2)<eps){ puts("=")