HDU 4773 圆的反演(经典
来源:互联网 发布:spss绘制散点图矩阵 编辑:程序博客网 时间:2024/06/03 20:23
题目链接
参考博客
题意:给定两个相离的圆和圆外定点
思路:
圆的反演变换入门题。
掌握两个关于圆反演的性质即可解决该问题。
一是相切两圆的反相仍相切,若反相均为直线,则平行。
二是经过反演中心的圆,其反相为直线。
故我们可以以P为反演中心,任意值为反演半径。先求出两个已知圆的反演圆,则与两个反演圆外切的直线,其反演后一定满足:
(1).与两个圆的原形相切。
(2).一定通过反演中心P点。
因题目是求外切,故注意一下反演圆圆心和P点应在切线同一侧,这样就能保证切线反演以后是与原形外切的圆。
代码:
#include<cmath>#include<cstdio>#include<cstdlib>#include<cstring>#include<algorithm>using namespace std;typedef long long ll;const double eps = 1e-10;class Point{public: double x,y; Point(double _x=0,double _y=0):x(_x),y(_y){} Point operator + (Point rhs){return Point(x+rhs.x,y+rhs.y);} Point operator - (Point rhs){return Point(x-rhs.x,y-rhs.y);} Point operator * (double rhs){return Point(x*rhs,y*rhs);} Point operator / (double rhs){return Point(x/rhs,y/rhs);} Point Move(double a,double d){return Point(x+d*cos(a),y+d*sin(a));} void Read(){scanf("%lf%lf",&x,&y);}}P;class Circle{public: Point o;double r; Circle(double _x=0,double _y=0,double _r=0):o(_x,_y),r(_r){} void Read(){o.Read();scanf("%lf",&r);} void out(){printf("%.8f %.8f %.8f\n",o.x,o.y,r);}}c[5];int Sign(double x){return (x>eps) - (x<-eps);}double Cross(Point a,Point b,Point c){return (b.x-a.x)*(c.y-a.y) - (c.x-a.x)*(b.y-a.y);}double Dis(Point a,Point b){return sqrt((a.x-b.x)*(a.x-b.x) + (a.y-b.y)*(a.y-b.y));}double R;int tot;Circle Inverse(Circle a){ Circle res; double oc1 = Dis(P,a.o); double k1 = 1.0 / (oc1 - a.r); double k2 = 1.0 / (oc1 + a.r); res.r = 0.5*(k1 - k2)*R*R; double oc2 = 0.5*(k1 + k2)*R*R; res.o =P + (a.o - P)*oc2 / oc1; return res;}void Mark(Point a,Point b){ ++tot; double tem = fabs(Cross(a,P,b)/Dis(a,b))*2.0; c[tot].r = R*R/tem; double d = Dis(a,c[0].o); c[tot].o = P + (a-c[0].o)*(c[tot].r/d);}void solve(){ for(int i=0 ;i<2 ;i++) c[i] = Inverse(c[i]); if(c[0].r < c[1].r) swap(c[0],c[1]); Point tem = c[1].o - c[0].o; double a1 = atan2(tem.y,tem.x); double a2 = acos((c[0].r - c[1].r)/Dis(c[0].o,c[1].o)); Point P1 = c[0].o.Move(a1+a2,c[0].r); Point P2 = c[1].o.Move(a1+a2,c[1].r); if(Sign(Cross(P1,c[0].o,P2)) == Sign(Cross(P1,P,P2))) Mark(P1,P2); P1 = c[0].o.Move(a1-a2,c[0].r); P2 = c[1].o.Move(a1-a2,c[1].r); if(Sign(Cross(P1,c[0].o,P2)) == Sign(Cross(P1,P,P2))) Mark(P1,P2);}int main(){ R = 5.0; //保证精度的前提下任意取的反演半径 int T;scanf("%d",&T); while(T--){ tot = 1; for(int i=0 ;i<2 ;i++) c[i].Read(); P.Read(); solve(); printf("%d\n",tot-1); for(int i=2 ;i<=tot ;i++) c[i].out(); } return 0;}
阅读全文
0 0
- HDU 4773 圆的反演(经典
- hdu 4773 圆的反演变换
- hdu-6158-圆的反演
- HDU 6158 圆的反演
- HDU 4773 Problem of Apollonius 圆的反演
- [圆的反演] HDU 4773 Problem of Apollonius
- HDU 6097 Mindis(圆的反演)
- hdu 4773 几何反演 线->圆
- HDU 4773 反演变换
- 圆的反演变换
- 圆的反演
- 圆的反演
- 圆的反演
- 圆的反演模版
- 【圆的反演变换】hdu4773
- Mindis(圆的反演变换)
- 圆的反演+计算几何
- 圆的反演变换(*)
- 快速排序的实现与使用
- 网络爬虫相关知识点
- 嵌套类:静态嵌套类和非静态嵌套类
- ubuntu安装最新版本mysql
- 使用scikit-image包的io模块导入图片
- HDU 4773 圆的反演(经典
- poj1094(拓扑排序)
- BIOS功能思维导图-根据《Linux内核完全剖析》
- IDEA+Maven整合Spring与MyBatis框架
- c++学习 *s++,*(s++),(*s)++,*++s,++*s
- 用BitSet来替代HashSet
- Android开发 第14课 App签名打包
- Drawable setBounds()中的rect
- python文件读写