【模板】【计几】圆的反演

hdu4773:http://acm.hdu.edu.cn/showproblem.php?pid=4773

题意:给你两个相离的圆,以及一个点,求所有和这两个圆相切,并且经过该点的圆。

我们先画出满足题意的圆,然后把这三个圆反演,给定的两个圆因为不经过p点,反演后是两个圆,然后ans圆经过p点,所以反演后是一条直线,又因为和两个圆相切,所以反演出来的直线也是和两个圆相切的,所以就是两个反演圆的外公切线了(不可以是内公切先,画画图就明白了)。

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define eps 1e-6
 4 int sgn(double x){
 5     if( fabs(x) < eps) return 0;
 6     if( x < 0) return -1;
 7     return 1;
 8 }
 9 struct Point{
10     double x,y;
11     Point operator - (const Point& b){
12         return (Point){ x - b.x,y-b.y};
13     }
14     Point operator + (const Point& b){
15         return (Point){x+b.x,y+b.y};
16     }
17     Point operator * (const double& b){
18         return (Point){b * x,b * y};
19     }
20     Point Move(double a,double d){
21         return (Point){ x + d * cos(a),y + d * sin(a)};
22     }
23 };
24 struct Circle{
25     Point o;
26     double r;
27 }c[3],c0,ansc[3];
28 int tot;
29 double cross(Point a,Point b,Point c){
30     return (b.x - a.x) * (c.y - a.y) - (c.x - a.x)*(b.y - a.y);
31 }
32 double dot(Point a,Point b,Point c){
33     return (b.x - a.x) * (c.x - a.x) + (b.y - a.y) * (c.y - a.y);
34 }
35 double dis(Point a,Point b){
36     return sqrt( (a.x - b.x) * (a.x - b.x) + (a.y - b.y)*(a.y - b.y));
37 }
38 Point Point_Inver(Circle c0,Point P){
39     Point OP = P - c0.o;
40     double len = dis(c0.o,P);
41     len = len*len;
42     return c0.o + OP*( c0.r * c0.r / len );
43 }
44 Circle Circle_Inver(Circle c0,Circle a){
45     Circle res;
46     Point OA = a.o - c0.o;
47     double len = dis(a.o,c0.o);
48     Point up = c0.o + OA * ( ( len + a.r) / len );
49     Point down = c0.o + OA *( (len - a.r) / len );
50     up = Point_Inver(c0,up);
51     down = Point_Inver(c0,down);
52     res.o = (up+down) * 0.5;
53     res.r = dis(up,down) * 0.5;
54     return res;
55 }
56 Circle Line_Inver(Circle c0,Point a,Point b){
57     Circle res;
58     double d = fabs( cross(a,c0.o,b) / dis(a,b));
59     res.r = c0.r * c0.r / (2.0 * d);
60
61     double len = dot(a,b,c0.o) / dis(a,b);
62     Point AB = b - a;
63     Point c = a + AB * (len/dis(a,b));
64     Point CO = c - c0.o;
65     res.o = c0.o + CO * (res.r/d);
66
67     //double len = dis(a,c[1].o);
68     //res.o = c0.o + (a-c[1].o) * (res.r/len);
69     return res;
70 }
71 void solve(){
72     for(int i = 1;i<=2;++i) c[i] = Circle_Inver(c0,c[i]);
73     if( c[1].r < c[2].r - eps) swap(c[1],c[2]);
74     Point v = c[2].o - c[1].o;
75     double a1 = atan2(v.y,v.x);
76     double a2 = acos( (c[1].r - c[2].r) / dis(c[1].o,c[2].o));
77     Point p1 = c[1].o.Move(a1 + a2,c[1].r);
78     Point p2 = c[2].o.Move(a1 + a2,c[2].r);
79     //cerr<<p1.x<<" "<<p1.y<<" "<<p2.x<<" "<<p2.y<<endl;
80     if( sgn(cross(c[1].o,p1,p2)) == sgn(cross(c0.o,p1,p2)) ) ansc[++tot] = Line_Inver(c0,p1,p2);
81     p1 = c[1].o.Move(a1-a2,c[1].r);
82     p2 = c[2].o.Move(a1-a2,c[2].r);
83     //cerr<<p1.x<<" "<<p1.y<<" "<<p2.x<<" "<<p2.y<<endl;
84     if( sgn(cross(c[1].o,p1,p2)) == sgn(cross(c0.o,p1,p2)) ) ansc[++tot] = Line_Inver(c0,p1,p2);
85 }
86 int main(){
87     c0.r = 10.0;
88     int T; scanf("%d",&T);
89     while(T--){
90         tot = 0;
91         for(int i = 1;i<=2;++i) scanf("%lf %lf %lf",&c[i].o.x,&c[i].o.y,&c[i].r);
92         scanf("%lf %lf",&c0.o.x,&c0.o.y);
93         solve();
94         printf("%d\n",tot);
95         for(int i = 1;i<=tot;++i) printf("%.8f %.8f %.8f\n",ansc[i].o.x,ansc[i].o.y,ansc[i].r);
96     }
97     return 0;
98 }

原文地址:https://www.cnblogs.com/xiaobuxie/p/12269588.html

时间: 2024-11-05 13:36:21

【模板】【计几】圆的反演的相关文章

2017多校第6场 HDU 6097 Mindis 计算几何,圆的反演

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6097 题意:有一个圆心在原点的圆,给定圆的半径,给定P.Q两点坐标(PO=QO,P.Q不在圆外),取圆上一点D,求PD+QD的最小值. 解法:圆的反演. 很不幸不总是中垂线上的点取到最小值,考虑点在圆上的极端情况. 做P点关于圆的反演点P',OPD与ODP'相似,相似比是|OP| : r. Q点同理. 极小化PD+QD可以转化为极小化P'D+Q'D. 当P'Q'与圆有交点时,答案为两点距离,否则最优

hdu 4773 圆的反演

第一次接触反演算法. 通过反演圆以求得反演后的直线. 圆的相切即为直线和圆的相切,切点是关键. 值得注意的是,不过中心的直线反演后得到不过中心的圆,圆圆反演后得到另一个圆,因为中途可以得到一条直线,所以可以简化计算. 反演半径不可以随意选取,过大会导致精度问题. #include <cstdio>#include <cstring>#include <cstdlib>#include <cmath>#include <vector>#includ

【科技】浅谈圆的反演

莫名其妙,一时兴起,就有了这篇博客. 首先我们要明白反演是什么. 反演是一种基本的几何变换.给定一个平面上的一个反演中心$O$和一个常数$k$,对于任意一个点$A$,我们可以找到一个在直线$OA$上的点$A'$,使得线段$OA,OA'$的有向长度的乘积为$k$,那$A'$就是$A$关于$O$的反演点,可以证明这样的$A'$是唯一的.我们称$A->A'$的这种变换为反演,我们也可以把它看成一种映射,而且是双射. 参考资料: 知乎zdr0的专栏 https://zhuanlan.zhihu.com/

hdu 6097 Mindis(数学几何,圆心的反演点)

Mindis Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 2787    Accepted Submission(s): 555Special Judge Problem Description The center coordinate of the circle C is O, the coordinate of O is (0,

hdu6206 Apple 2017 ACM/ICPC Asia Regional Qingdao Online

地址:http://acm.split.hdu.edu.cn/showproblem.php?pid=6206 题目: Apple Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others)Total Submission(s): 530    Accepted Submission(s): 172 Problem Description Apple is Taotao's favouri

【醒目】【业界偷懒】【Public】BZOJ题目一句话题解整理

就当是复习一下自己做过的题,顺便提供一个简要题解给大家看. 做题时候实在想不出来看一下一句话题解,可以有一个提示的作用又不至于一下子知道了全部浪费了一道题吧.. 部分题目(如我A过得大部分奶牛题)是别人拿我的账号做的,不提供题解. 可能会漏掉很多做过的题..因为可能点页数不小心点错了什么的 UPD.本来想把那些没写过但是知道题解的也写了..但是写完这些已经累死了QAQ 已AC的题目(数学题均不提供分析过程,公式): 1000:A+B 1001:平面图最小割,转对偶图最短路 1002:矩阵树定理,

设计模式_装饰模式

Decorator Pattern  Attach additional responsibilities to an object dynamically keeping the same interface. Decorators provide a  flexible alternative to subclassing for extending functionality.(动态地给一个对象添加一些额外的职责.就增加功能来说,装饰模式比生成子类更为灵活) 不认识的单词 dynamica

【自用】OI计划安排表一轮

网络流√ 上下界最大流√ 线性规划转费用流√ RMQ优化建图√ 单纯形√ 字符串相关 hash√ 扩展KMP 回文自己主动机 数据结构 平衡树 启示式合并 替罪羊树 LCT 树套树 KD-Tree 二分答案 分数规划√ 贪心 动态规划 斜率优化√ 数位DP√ 概率DP√ 插头DP 图论 差分约束√ floyd求最小环√ 连通分量相关√ 强连通分量√ 点双连通分量√ 边双连通分量√ 割点√ 割边√ 最小生成树√ Matrix-Tree定理√ 斯坦纳树√ 最小树形图√ 树上问题 Prufer序列 认

近期小计划...

几场区域赛下来... 暴露了很多不足,来定个小计划... (1)DLX 安装包 (2)Lucas 补丁(2013 Dhaka E) (3)Dilworth 安装包(poj 1065.3636,博文1,博文2) (4)树--巨型安装包(分治,重心,倍增,treap) (5)圆的反演 启蒙包(2013 杭州 D,博文1)