【题目概述】

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

【题目大意】:一个面积无限大的光滑桌面,一个质点从初始点A(x0,y0)出发,初速度为(Vx, Vy),桌子上有一个圆柱体,圆心(cx,cy),半径为R,小球如果与圆柱体碰撞则发生的是完全弹性碰撞,在桌子上某处有一点B(ex,ey),问这个质点能不能经过B点?

【题解】:简单的几何学。记小球初始从A点沿着射线L1运动,分两种情况讨论。

(1)小球能和圆柱体相撞,即L1与圆O有两个交点(如果相切认为不会发生碰撞改变方向),记碰撞点为G点(射线与圆相交的较近的那一点),那么小球碰撞后沿什么射线运动呢?连接OG,则小球沿着L1关于OG的对称直线L2运动,如果B点在射线L2上则满足题意,或者在未碰撞之前,即B在线段AG上,也满足题意。

(2)小球不能与圆柱体相撞。判断B是否在射线L1上,若在则满足题意。

【代码】

#include <algorithm>
#include <cstdio>
#include <vector>
#include <cmath>
using namespace std; const double eps = 1e-; //1e-10会WA,注意调整精度,过大过小都不行 //浮点数是否等于0,在eps精度范围之内
int dcmp(double x){
if(fabs(x) < eps) return ;
return x < ? - : ;
}
//自定义开方
double mySqrt(double x){
return sqrt(max((double), x));
} //点的结构体定义
struct Point
{
double x, y;
Point(double x=, double y=):x(x), y(y){}
Point& operator = (Point p){
x = p.x;
y = p.y;
return *this;
}
}; typedef Point Vector;
//向量四则运算定义
Vector operator + (Vector A, Vector B){ return Vector(A.x + B.x, A.y + B.y);}
Vector operator - (Point A, Point B){ return Vector(A.x - B.x, A.y - B.y);}
Vector operator * (Vector A, double p){ return Vector(A.x * p, A.y * p);}
Vector operator / (Vector A, double p){ return Vector(A.x / p, A.y / p);} //点乘定义
double dot(Vector A, Vector B){ return A.x * B.x + A.y * B.y;}
//模长定义
double length(Vector A){ return mySqrt(dot(A, A));}
//叉积定义
double cross(Vector A, Vector B){ return A.x * B.y - A.y * B.x;} //直线结构体
struct Line
{
//相当于点向式
// (x - x0) / v.x = (y - y0) / v.y
Point p;//直线上一点
Vector v;//方向向量定方向
Line(Point p, Vector v):p(p), v(v){}
Point getPoint(double t){
return Point(p.x + v.x*t, p.y + v.y*t);
}
}; //圆的结构体定义 圆心和半径即可
struct Circle
{
Point c;
double r;
Circle(Point c, double r):c(c), r(r){}
}; //求圆和直线交点 ,返回1有两个实数解,其他返回0
int getLineCircleIntersection(Line L, Circle C, Point& P){ //返回t较小的那个点
double a = L.v.x;
double b = L.p.x - C.c.x;
double c = L.v.y;
double d = L.p.y - C.c.y; double e = a*a + c*c;
double f = *(a*b + c*d);
double g = b*b + d*d - C.r*C.r; double delta = f*f - *e*g; //判别式大于0 一元二次方程才有实数解
if(dcmp(delta) <= ) return ;
//一元二次方程求根公式
double t = (-f - mySqrt(delta)) / (*e); P = L.getPoint(t);
return ;
} int getLineCircleIntersection2(Line L, Circle C, Point& P, Point& Q){ //返回两个点
double a = L.v.x;
double b = L.p.x - C.c.x;
double c = L.v.y;
double d = L.p.y - C.c.y; double e = a*a + c*c;
double f = *(a*b + c*d);
double g = b*b + d*d - C.r*C.r; double delta = f*f - *e*g; //判别式大于0 一元二次方程才有两个实数解
if(dcmp(delta) < ) return ;
//一元二次方程求根公式
double t1 = (-f - mySqrt(delta)) / (*e);
double t2 = (-f + mySqrt(delta)) / (*e);
P = L.getPoint(t1);
Q = L.getPoint(t2);
return ;
}
//点是否在直线上
bool onLine(Point A, Line L){
Vector w = A - L.p;
//printf("%lf %lf\n", w.x,w.y);
//叉积为0即共线
if(dcmp(cross(w, L.v)) == )
return true;
else return false;
} bool onRay(Point A, Line L){//点A在射线L(p,v)上,不含端点
Vector w = A - L.p;
//叉积等于0且点乘大于0
if(dcmp(cross(w, L.v))== && dcmp(dot(w, L.v)) > ) return true;
return false;
} bool onSeg(Point A, Point B, Point C){//点A在线段BC上
//叉积等于0且点乘小于0
return dcmp(cross(B-A, C-A))== && dcmp(dot(B-A, C-A))<;
} Point project(Point A, Line L){
return L.p + L.v * ( dot(L.v, A - L.p) / dot(L.v, L.v) );
} //求点A关于直线L的对称点
Point mirrorPoint(Point A, Line L){
Vector D = project(A, L);
//printf("project: %lf, %lf\n", D.x, D.y);
return D + (D - A);
} int main()
{
int T;
int ans = ;
double R;
Point O, A, B;
Vector V;
/*
A = Point(1,0);
V = Point(1,1);
Line L1 = Line(A,V); O.x = 2;
O.y = 0; Circle yuanO = Circle(O, 1);
int tt = getLineCircleIntersection2( L1, yuanO, A, B);
printf("%lf %lf\n",A.x,A.y);
printf("%lf %lf\n",B.x,B.y);
*/
/* A = Point(1,0);
V = Point(1,1);
Line l1 = Line(A,V);
printf("%lf %lf %lf %lf\n",l1.p.x,l1.p.y,l1.v.x,l1.v.y);
B = Point();
while(scanf("%lf%lf", &B.x, &B.y) != EOF){
printf("%lf %lf\n",B.x,B.y);
printf("%d\n",onLine( B, l1));
}*/ scanf("%d", &T);
for(int ca = ; ca <= T; ca++){ scanf("%lf%lf%lf", &O.x, &O.y, &R);
scanf("%lf%lf%lf%lf", &A.x, &A.y, &V.x, &V.y);
scanf("%lf%lf", &B.x, &B.y); Line LA = Line(A, V);
Circle yuanO = Circle(O, R);
Point C; if(getLineCircleIntersection(LA, yuanO, C)){
if(onSeg(B, A, C)) ans = ;
else{
//直线OC是对称轴
Line OC = Line(O, Vector(C.x - O.x, C.y - O.y));
Point A1 = mirrorPoint(A, OC);
// printf("%lf, %lf\n", C.x, C.y);
// printf("%lf, %lf\n", A1.x, A1.y); //射线CB
Line CB = Line(C, Vector(B.x - C.x, B.y - C.y)); if(onRay(A1, CB)){
ans = ; }
else ans = ;
}
}else{
if(onRay(B, LA)) ans = ;
else ans = ;
}
printf("Case #%d: %s\n", ca, ans ? "Yes" : "No");
} return ;
}

判断线段是否相交,点是否在矩形内

//判断一个点是否在矩形内部
#include<cstdio>
#include<iostream>
using namespace std; typedef struct Point
{
double x;
double y;
Point(){
} Point(double x,double y)
{
this->x = x;
this->y = y;
}
}point;
// 计算 |p1 p2| X |p1 p|
double GetCross(point p1,point p2,point p)
{
return (p2.x - p1.x) * (p.y - p1.y) -(p.x - p1.x) * (p2.y - p1.y);
} //判断点是否在正方形内(便于测试)
bool IsPointInMatrix(point p, point p1, point p2, point p3, point p4)
{
return GetCross(p1,p2,p) * GetCross(p3,p4,p) >= && GetCross(p2,p3,p) * GetCross(p4,p1,p) >= ;
//return false;
} double Cross_Prouct(point A,point B,point C) // 计算BA叉乘CA;
{
return (B.x-A.x)*(C.y-A.y)-(B.y-A.y)*(C.x-A.x);
} bool Intersect(point A,point B,point C,point D) // 通过叉乘判断线段是否相交;
{
if(min(A.x,B.x)<=max(C.x,D.x)&& // 快速排斥实验;
min(C.x,D.x)<=max(A.x,B.x)&&
min(A.y,B.y)<=max(C.y,D.y)&&
min(C.y,D.y)<=max(A.y,B.y)&&
Cross_Prouct(A,B,C)*Cross_Prouct(A,B,D)<=&& // 跨立实验;
Cross_Prouct(C,D,A)*Cross_Prouct(C,D,B)<=) // 叉乘异号表示在两侧;
return true;
else return false;
} int main()
{
bool f1 = , f2 = , flag = ; point pset1[];
point pset2[];
for(int i=; i<; i++) cin>>pset1[i].x>>pset1[i].y;
for(int i=; i<; i++) cin>>pset2[i].x>>pset2[i].y; for(int i=; i<; i++){
bool b = IsPointInMatrix(pset1[i], pset2[], pset2[], pset2[], pset2[]);
//cout<<b<<endl;
if(!b){
f1 = ;
} } for(int i=; i<; i++){
bool b = IsPointInMatrix(pset2[i], pset1[], pset1[], pset1[], pset1[]);
//cout<<b<<endl;
if(!b){
f2 = ;
}
} if(f1 || f2){
cout<<"YES"<<endl;
return ;
} //cout<<11111111111111<<endl;
for(int i=; i<; i++){
for(int j=; j<; j++){ bool b = Intersect(pset1[i], pset1[(i+)%],pset2[j],pset2[(j+)%]);
//cout<<b<<endl; if(b){
flag = ;
break;
}
}
if(flag) break;
}
if(flag) cout<<"YES"<<endl;
else cout<<"NO"<<endl; return ;
}

HDU - 5572 An Easy Physics Problem (计算几何模板)的更多相关文章

  1. HDU 5572 An Easy Physics Problem (计算几何+对称点模板)

    HDU 5572 An Easy Physics Problem (计算几何) 题目链接http://acm.hdu.edu.cn/showproblem.php?pid=5572 Descripti ...

  2. hdu 5572 An Easy Physics Problem 圆+直线

    An Easy Physics Problem Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/ ...

  3. HDU 5572 An Easy Physics Problem【计算几何】

    计算几何的题做的真是少之又少. 之前wa以为是精度问题,后来发现是情况没有考虑全... 题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5572 题意: ...

  4. 【HDU 5572 An Easy Physics Problem】计算几何基础

    2015上海区域赛现场赛第5题. 题目连接:http://acm.hdu.edu.cn/showproblem.php?pid=5572 题意:在平面上,已知圆(O, R),点B.A(均在圆外),向量 ...

  5. 2015 ACM-ICPC 亚洲区上海站 A - An Easy Physics Problem (计算几何)

    题目链接:HDU 5572 Problem Description On an infinite smooth table, there's a big round fixed cylinder an ...

  6. HDU 5572--An Easy Physics Problem(射线和圆的交点)

    An Easy Physics Problem Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/ ...

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

    题意: 光滑平面,一个刚性小球,一个固定的刚性圆柱体 ,给定圆柱体圆心坐标,半径 ,小球起点坐标,起始运动方向(向量) ,终点坐标 ,问能否到达终点,小球运动中如果碰到圆柱体会反射. 学到了向量模板, ...

  8. HDU 5130 Signal Interference(计算几何 + 模板)

    HDU 5130 Signal Interference(计算几何 + 模板) 题目链接http://acm.hdu.edu.cn/showproblem.php?pid=5130 Descripti ...

  9. HDU 4974 A simple water problem(贪心)

    HDU 4974 A simple water problem pid=4974" target="_blank" style="">题目链接 ...

随机推荐

  1. 思维 || Make It Equal

    http://codeforces.com/contest/1065/problem/C 题意:给你n个高度分别为a[i]的塔,每次可以横着切一刀,切掉不多于k个塔,问最少切多少刀才能把塔切的都一样高 ...

  2. javase(11)_juc并发库

    一.传统线程技术 public static void main(String[] args) { Thread thread = new Thread(){ @Override public voi ...

  3. 把所有界面的状态栏字体颜色设置为白色--iOS开发系列---项目中成长的知识一

    第一步: 在info.plist中 View controller-based status bar appearance这个属性设置为 View controller-based status ba ...

  4. EAGLView介绍

    http://book.51cto.com/art/201108/285446.htm

  5. ios 检查内存泄露

    简介 在IPhone程式开发中,记忆体泄漏(内存泄漏)是个很容易发生的情况,因为IPhone必须自行作记忆体管理.现在的开发者,大多习惯用的.NET或Java的等有垃圾回收机制的开发语言来作开发,因此 ...

  6. Luogu P4231 三步必杀 (差分)

    目录 题目 题解 题目 题目链接 题目背景 (三)旧都 离开狭窄的洞穴,眼前豁然开朗. 天空飘着不寻常的雪花. 一反之前的幽闭,现在面对的,是繁华的街市,可以听见酒碗碰撞的声音. 这是由被人们厌恶的鬼 ...

  7. 【OS_Linux】三大文本处理工具之sed命令

    1.sed命令的简介及用法 sed:即为流编辑器,“stream editor”的缩写.他先将源文件读取到临时缓存区(也叫模式空间)中,再对满足匹配条件的各行执行sed命令.sed命令只针对缓存区中的 ...

  8. dubbo---------timeout与retires

    相信很多人都见过这张图,这张图说明了提供者与消费者之间的关系,下面就介绍一下这个图是什么意思. 1.角色解释: Provider: 暴露服务的服务提供者. Consumer: 调用远程服务的服务消费者 ...

  9. Linux基础学习系列目录导航

    Linux基础学习-通过VM安装RHEL7.4 Linux基础学习-命令行与图形界面切换 Linux基础学习-基本命令 Linux基础学习-RHEL7.4之YUM更换CentOS源 Linux基础学习 ...

  10. 本地开发环境中部署已经写好的magento2.0项目

    环境:apache2.4.25+php7.0.16+mysql5.7 (注意版本搭配,详细可以看magento2.0官网看配置) apache最好使用80端口,host文件配置本地虚拟域名 php.i ...