HDU 5572 An Easy Physics Problem (计算几何 点类 线类 向量类 线段与圆相交)
2017-10-19 21:21
459 查看
题目链接
2015上海区域赛现场赛第5题 HDU5572题目大意
光滑平面上,有一个固定的圆,圆外有两点A,B,问A以速度矢量V运动能否碰到B。(A碰到圆后会发生弹性碰撞)分析
写这道题的时候没有想清楚就开始写了,比赛的时候一定要先把思路理清楚,情况比较多的题要画画树状图或者流程图。看了一个大佬的博客中画了一个清晰的流程图,借鉴一下。
原博客链接
代码
#include<cstdio> #include<iostream> #include<cmath> #include<cstring> #include<cstdlib> #include<queue> #include<map> #include<algorithm> #include<set> #include<stack> using namespace std; typedef long long int LL; typedef long double LD; const long double eps=1e-8; int dcmp(long double x) { if (fabs(x)<eps) return 0; if (x>0) return 1; return -1; } long double mysqrt(long double x) { return sqrt(max((long double)0,x)); } struct Point ///点类 { long double x,y; Point() {} Point(long double a,long double b):x(a),y(b){} void input() { cin>>x>>y; } friend bool operator == (const Point &a,const Point &b) { return dcmp(a.x-b.x)==0 && dcmp(a.y-b.y)==0; } }; typedef Point Vector;///向量类 Vector operator + (Vector A,Vector B) {return Vector(A.x+B.x,A.y+B.y);} Vector operator - (Vector A,Vector B) {return Vector(A.x-B.x,A.y-B.y);} Vector operator * (Vector A,long double t) {return Vector(A.x*t,A.y*t);} Vector operator / (Vector A,long double t) {return Vector(A.x/t,A.y/t);} long double dot(Vector A,Vector B) {return A.x*B.x+A.y*B.y;} long double cross(Vector A,Vector B){return A.x*B.y-A.y*B.x;} long double length(Vector A) {return mysqrt(dot(A,A));} /*long double angle(Vector A,Vector B) {return acos(dot(A,B)/length(A)/length(B));}///求两向量夹角 Vector Rotate(Vector A,long double rad)///向量A绕起点逆时针旋转rad弧度 { return Vector(A.x*cos(rad)-A.y*sin(rad),A.x*sin(rad)+A.y*cos(rad)); }*/ struct Line///线类 { Point p; Vector v; Line (Point p,Vector v):p(p),v(v){} Point getPoint(long double t)///得到线上的一点 { return Point(p.x+t*v.x,p.y+t*v.y); } }; Point project(Point A,Line L) { return L.p+L.v*(dot(L.v,A-L.p)/dot(L.v,L.v)); } Point mirrorPoint(Point A,Line L) { Vector D=project(A,L); return D+(D-A); } void circle_cross_line(Point a,Point b,Point o,long double r,Point ret[],int &num)///求线段与圆交点模板 { long double x0=o.x,y0=o.y; long double x1=a.x,y1=a.y; long double x2=b.x,y2=b.y; long double dx=x2-x1,dy=y2-y1; long double A=dx*dx+dy*dy; long double B=2*dx*(x1-x0)+2*dy*(y1-y0); long double C=(x1-x0)*(x1-x0)+(y1-y0)*(y1-y0)-r*r; long double delta=B*B-4*A*C; num=0; if (dcmp(delta)>=0) { long double t1=(-B-mysqrt(delta))/(2*A); long double t2=(-B+mysqrt(delta))/(2*A); if (dcmp(t1)>=0) ret[++num]=Point(x1+t1*dx,y1+t1*dy); if (dcmp(t2)>=0) ret[++num]=Point(x1+t2*dx,y1+t2*dy); } } int get_dis(Point a,Point b) { return ( (a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y)); } bool onRay(Point A,Line L)///判断点A是否在射线L(p,v)上 { Vector w=A-L.p; return (dcmp(cross(w,L.v))==0&&dcmp(dot(w,L.v))>0); } bool onSeg(Point A,Point B,Point C)///判断点A是否在线段BC上 { return (dcmp(cross(B-A,C-A))==0 && dcmp(dot(B-A,C-A))<0); } int main() { int T,temp1,temp2,tot; Point O,A,AA,A1,B,C,ret[5],p1,p2,p3; Vector V; long double r; scanf("%d",&T); for (int tt=1;tt<=T;tt++) { printf("Case #%d: ",tt); O.input();cin>>r; A.input();V.input(); Line LA=Line(A,V); AA=LA.getPoint(1.0); B.input(); circle_cross_line(A,AA,O,r,ret,tot); if (tot==2&&ret[1]==ret[2])///用这个模板相同的交点会存两次 tot--; if (tot<=1)///如果圆没有改变A的运动轨迹(射线与圆相离或相切) { if (onRay(B,LA)) printf("Yes\n"); else printf("No\n"); continue; } temp1=get_dis(A,ret[1]); temp2=get_dis(A,ret[2]); if (temp1<temp2)///离A最近的那个交点为碰撞点C C=ret[1]; else C=ret[2]; if (onSeg(B,A,C))///如果B在线段AC上 printf("Yes\n"); else { Line OC=Line(O,C-O); A1=mirrorPoint(A,OC);///做A关于OC的对称点AC if (onRay(B,Line(C,A1-C)))///判断B是否在射线CA1上 printf("Yes\n"); else printf("No\n"); } } return 0; }
相关文章推荐
- HDU 5572 An Easy Physics Problem (物理、计算几何)
- HDU 5572 An Easy Physics Problem【计算几何】
- HDU 5572 An Easy Physics Problem【计算几何】
- HDU 5572 An Easy Physics Problem(计算几何)——2015ACM/ICPC亚洲区上海站-重现赛
- 【HDU 5572 An Easy Physics Problem】计算几何基础
- HDU - 5572 An Easy Physics Problem(计算几何)
- POJ 2826 An Easy Problem?! (计算几何、线段相交、思维)
- hdu 5572 An Easy Physics Problem(几何)
- hdu 1086:You can Solve a Geometry Problem too(计算几何,判断两线段相交,水题)
- 简单几何(线段相交) POJ 2826 An Easy Problem?!
- [HDU 5572] An Easy Physics Problem (点在线上判定+对称)
- HDU5572 An Easy Physics Problem 【计算几何】
- HDU 5572-An Easy Physics Problem (计算几何)
- An Easy Physics Problem HDU - 5572 直线与圆
- HDU-5572-An Easy Physics Problem
- 计算几何 POJ 2826 An Easy Problem?! (线段位置判断并且求交点)
- hdu 5572 An Easy Physics Problem
- hdu 5572 An Easy Physics Problem
- poj-2826 An Easy Problem?!(计算几何,好题)
- An Easy Problem?!(poj2826线段相交,直线线段相交)