HDU4773:Problem of Apollonius(圆的反演)
来源:互联网 发布:视频软件管理条例2017 编辑:程序博客网 时间:2024/06/07 01:02
传送门
题意:
给两个相离的圆,和圆外的点,求过这个点与两圆外切的所有圆。
题解:圆的反演
考的是数学啊。。不过向量很好做。
首先推荐看看圆的反演入门知识:http://blog.csdn.net/acdreamers/article/details/16966369
有两点个人觉得很重要,由于本人太辣鸡不会证明,就做了两个gif图。
(CSDN不能放高清图,凑合凑合看吧。。。)
1.当两圆外切时,若切点是反演点,那么两直线相交,若只有一个圆在反演点上,那么反演后的图形为圆+切线,且圆心与反演点在切线同一方向(判断是否合法)。
2.反演不影响相交,相切性质。(也就是说相离的两个点反演只有也相离)
之后就比较简单了:
做出两圆关于反演圆的对称圆,之后做出四条交线(其实只需要外公切线,因为内公切线必有一个圆是外切,一个圆是内切(性质1))。
用性质2判断合法性后反演回去就行了。
至于怎么反演。。用向量做就行了。
#include<cstdio>#include<iostream>#include<cmath>#include<iomanip>using namespace std;const double PI=acos(-1.0);struct point{ double x,y; point(double x=0,double y=0):x(x),y(y){} friend inline point operator +(const point &a,const point &b){return point(a.x+b.x,a.y+b.y);} friend inline point operator -(const point &a,const point &b){return point(a.x-b.x,a.y-b.y);} friend inline point operator *(const point &a,double o){return point(a.x*o,a.y*o);} friend inline point operator /(const point &a,double o){return point(a.x/o,a.y/o);} friend inline double operator *(const point &a,const point &b){return a.x*b.y-a.y*b.x;} inline point rev(double theta){return point(x*cos(theta)-y*sin(theta),x*sin(theta)+y*cos(theta));} inline point normalvector(){return point(-y,x);} inline double len(){return sqrt(x*x+y*y);} friend inline point mid(const point &a,const point &b){return point((a.x+b.x)/2.0,(a.y+b.y)/2.0);}}p1,p2,p0,p11,p21;struct line{ point a,b; line(){} line(point a,point b):a(a),b(b){} friend inline point inter(const line &a,const line &b){ double k1=(a.b-b.a)*(a.a-b.a); double k2=(a.a-b.b)*(a.b-b.b); #define t k1/(k1+k2) return point(b.a.x+(b.b.x-b.a.x)*t,b.a.y+(b.b.y-b.a.y)*t); #undef t }};const double reflect_redius=10.0;#define powr 100.0double r1,r2,r11,r21;point ans[5];double ans2[5];int tot,T;inline void reflect(const point &p,const double &r,point &tar,double &tarr){ point to=(p-p0);double dis=to.len(); point A=p0+(to/dis*powr/(dis-r)),B=p0+(to/dis*powr/(dis+r)); tar=mid(A,B);tarr=(A-B).len()/2.0;}inline bool theSameSide(const point &a,const point &b,const line &l){ return (l.b-b)*(l.a-b)*((l.a-a)*(l.b-a))<0;}inline void reflect(const line &l){ point q=inter(l,line(p0,(l.b-l.a).normalvector()+p0)); q=p0+(q-p0)/(q-p0).len()*powr/(q-p0).len(); ans[++tot]=mid(q,p0);ans2[tot]=(q-p0).len()/2.0;}inline void getTangentLine(){ if(r11<r21)swap(p11,p21),swap(r11,r21); double theta=asin((r11-r21)/(p11-p21).len()); point to=(p11-p21);to=to.rev(theta); point o=to.rev(PI/2.0)/to.len()*r21; line l(p21+o,to+p21+o); if(theSameSide(p0,p11,l)&&theSameSide(p0,p21,l)){ reflect(l); } to=(p11-p21);to=to.rev(2.0*PI-theta); o=to.rev(1.5*PI)/to.len()*r21; l=line(p21+o,to+p21+o); if(theSameSide(p0,p11,l)&&theSameSide(p0,p21,l)){ reflect(l); }}int main(){ scanf("%d",&T); for(int tt=1;tt<=T;++tt,tot=0){ scanf("%lf%lf%lf",&p1.x,&p1.y,&r1); scanf("%lf%lf%lf",&p2.x,&p2.y,&r2); scanf("%lf%lf",&p0.x,&p0.y); reflect(p1,r1,p11,r11),reflect(p2,r2,p21,r21); getTangentLine(); printf("%d\n",tot); for(int i=1;i<=tot;i++)printf("%.8f %.8f %.8f\n",ans[i].x,ans[i].y,ans2[i]); }}
阅读全文
0 0
- HDU4773:Problem of Apollonius(圆的反演)
- hdu4773 Problem of Apollonius【反演变换】
- HDU 4773 Problem of Apollonius 圆的反演
- [圆的反演] HDU 4773 Problem of Apollonius
- 圆的反演变换(HDU4773)
- 【圆的反演变换】hdu4773
- [HDU 4773 Problem of Apollonius] 多圆相切问题+反演变换
- hdu 4773 Problem of Apollonius
- 如何构造Apollonius圆?
- Apollonius圆和反复计算得到的图案
- 圆的反演变换(*)
- bzoj 2301: [HAOI2011]Problem b (反演)
- 是的,就连这种Apollonius圆图案也很容易做成GIF动画的形式
- HDU 6097 Mindis(圆的反演)
- 圆的反演变换
- 圆的反演
- 圆的反演
- 圆的反演
- HDU 1150 二分图最小顶点覆盖 解题报告
- Qt5 text_Editor(二)
- 栈的应用
- [USACO07JAN]保护花朵(贪心策略)
- 组件化开发
- HDU4773:Problem of Apollonius(圆的反演)
- Selenium常用函数
- Idea注册码生成(有效期1年)
- 何凤文博客正式开通
- 4009.步步为赢
- 指针
- 完全掌握Android Data Binding
- 多项式相乘的另一解法
- Android中Canvas绘图方法的实现