HDU
来源:互联网 发布:微电影制作软件 编辑:程序博客网 时间:2024/06/09 22:16
点我看题
题意:一个点A(ax,ay)沿着某个方向(vx,vy)移动,有一个圆心为O(ox,oy)半径为r的圆,若点撞到圆会反弹且没有能量损失,问在这个点的行走过程中,能不能经过点B(bx,by).
分析:拿到题目就想到扥两种情况,①没有撞到圆;②撞到圆
对于没有撞到圆的情况,只要判断一直往下走的过程中是否会经过点B;
如果撞到圆,就要看在撞到圆之前是否会经过B,不经过的话,看反弹之后会不会经过B.
//设入射线的极角方程为x=vx*t+ax,y=vy*t+ay
//圆的方程为(x-ox)^2+(y-oy)^2 = r^2
//联立两个方程组得到(vx^2+vy^2)*t^2+2*((ax-ox)*vx+(ay-oy)*vy)*t+((ax-ox)^2+(ay-oy)^2-r^2) = 0
首先联立直线(用极角方程)与圆的方程,看delta是否大于0,如果大于0且b小于0(两根都要大于0的,即-b/a>0),求出较小的t(想想为什么),然后求出交点,接着可以求出切线方程(emmm自己求得是法线结果wa了好久),再求出B点关于切线方程的反对称点C,看C是否在A的射线上.
参考代码:
/*计算几何*/#include<cstdio>#include<cmath>#include<cstring>#include<algorithm>#include<iostream>using namespace std;#define eps 1e-8double ox,oy,r;double ax,ay,vx,vy;double bx,by;int sgn( double x){ if( fabs(x) < eps) return 0; if( x > 0) return 1; return -1;}inline double sqr( double x){ return x*x;}int main(){ int T; scanf("%d",&T); while( T--) { scanf("%lf%lf%lf",&ox,&oy,&r); scanf("%lf%lf%lf%lf",&ax,&ay,&vx,&vy); scanf("%lf%lf",&bx,&by); static int cas = 1; printf("Case #%d: ",cas++); //设入射线的极角方程为x=vx*t+ax,y=vy*t+ay //圆的方程为(x-ox)^2+(y-oy)^2 = r^2 //联立两个方程组得到(vx^2+vy^2)*t^2+2*((ax-ox)*vx+(ay-oy)*vy)*t+((ax-ox)^2+(ay-oy)^2-r^2) = 0 double a = sqr(vx)+sqr(vy); double b = 2*((ax-ox)*vx+(ay-oy)*vy); double c = sqr(ax-ox)+sqr(ay-oy)-sqr(r); //delta大于0,表示有两个根,-b/2a>0(使方程有两个正根) if( sgn( b*b-4*a*c) > 0 && sgn(b) < 0) { double tp = (-b-sqrt(b*b-4*a*c))/(2.0*a);//取较小的根,因为第一个交点肯定距离A点近一点 double px = vx*tp+ax;//入射线与圆的交点 double py = vy*tp+ay; //判断B是否在入射线上 if( vx != 0) { double t = (bx-ax)/vx; if( sgn(by-vy*t-ay) == 0 && sgn(t-tp) <= 0) { puts("Yes"); continue; } } else if( vy != 0) { double t = (by-ay)/vy; if( sgn(bx-vx*t-ax) == 0 && sgn(t-tp) <= 0) { puts("Yes"); continue; } } //求切线方程Ax+By+C=0 double A = px-ox; double B = py-oy; double C = (ox-px)*px+(oy-py)*py; //求B点关于法线的反对称点 double cx = bx-2.0*A*(A*bx+B*by+C)/(sqr(A)+sqr(B)); double cy = by-2.0*B*(A*bx+B*by+C)/(sqr(A)+sqr(B)); if( sgn(vx) != 0) { double t = (cx-ax)/vx; if( sgn(cy-vy*t-ay) == 0 && sgn(t) > 0)//>0??? puts("Yes"); else puts("No"); } else if( sgn(vy) != 0) { double t = (cy-ay)/vy; if( sgn(cx-vx*t-ax) == 0 && sgn(t) > 0) puts("Yes"); else puts("No"); } } else//射线 { if( sgn(vx) != 0) { double t = (bx-ax)/vx; if( sgn(by-vy*t-ay) == 0 && sgn(t) > 0) puts("Yes"); else puts("No"); } else if( sgn(vy) != 0) { double t = (by-ay)/vy; if( sgn(bx-vx*t-ax) == 0 && sgn(t) > 0) puts("Yes"); else puts("No"); } } } return 0;}
阅读全文
0 0
- hdu
- hdu
- HDU
- hdu ()
- hdu
- hdu
- HDU
- HDU
- hdu
- hdu
- HDU
- Hdu
- hdu
- hdu-
- hdu
- hdu
- hdu
- HDU
- HDU5044【LCA+差分】
- 笔试_oracle(8)
- python3中使用map,reduce和filter
- Python Flask(六) 大型网站架构
- win7如何设置电脑定时关机
- HDU
- surface重装系统
- 【LeetCode】Remove Nth Node From End of List 删除链表中倒数第n个节点- Easy +
- idea中【java排错】java.lang.ClassNotFoundException: com.mysql.jdbc.Driver
- 2017.10.15最新可用sdk更新镜像
- 使用Maven编译项目遇到——“maven编码gbk的不可映射字符”解决办法
- JavaWeb之JSP--------------JSP小结
- 打造一个轻量级,简单,易用的Android Banner框架
- Java:封装案例(再续)