圆的反演(hdu4773,hdu6158,hdu6097)

hdu4773http://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 }
View Code

 

 

hdu6158:http://acm.hdu.edu.cn/showproblem.php?pid=6158 

 

 给你这两个大圆的半径,问你往里面塞n个小圆,这n个小圆面积和是多少。

题解:很明显是以左边的切点做圆心,半径1的圆,对这两个大圆做圆的反演,然后就反演出两条平行直线了(画画图发现两条直线平行y轴),其他小圆因为和两大圆相切,所以和两直线相切,也就是夹在中间的那一堆圆,直接算就OK了。

参考博客:https://www.cnblogs.com/flipped/p/7397942.html

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define eps 1e-8
 4 const double rr = 1.0;
 5 const double pi = acos(-1.0);
 6 double r1,r2;
 7 int n;
 8 double area(double x){return pi*x*x;}
 9 double yan(int id){
10     double x = rr*(r2 + r1)/r1/r2/4;
11     double r = rr/r1/2 - x;
12     double y = 2 * id * r;
13     double len = sqrt(x*x+y*y);
14     double d1 = len - r,d2 = len + r;
15     double R = rr * ( 1/d1 - 1/d2) * 0.5;
16     return area(R);
17 }
18 double solve(){
19     double ans = 0;
20     ans += area( (r2-r1) );
21     --n;
22     for(int i = 1;i<=(n+1)/2;++i){
23         double tem = yan(i);
24         ans += tem;
25         if( i * 2 <= n ) ans += tem;
26         if( tem * (n-i*2) < eps ) break;
27     }
28     return ans;
29 }
30 int main(){
31     int T; scanf("%d",&T);
32     while(T--){
33         scanf("%lf %lf",&r1,&r2);
34         if(r1 > r2) swap(r1,r2);
35         scanf("%d",&n);
36         printf("%.5f\n",solve());
37     }
38     return 0;
39 }
View Code

 

hdu6097http://acm.hdu.edu.cn/showproblem.php?pid=6097

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define eps 1e-6
 4 struct Point{
 5     double x,y;
 6 }p1,q1,p2,q2,o;
 7 double dis2(Point a,Point b){
 8     return (a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y);
 9 }
10 double dis(Point a,Point b){
11     return sqrt( dis2(a,b) );
12 }
13 double r;
14 Point change(Point a){
15     Point res = a;
16     double len2 = dis2(a,o);
17     res.x = a.x * ( r * r /len2);
18     res.y = a.y * ( r * r /len2);
19     return res;
20 }
21 void solve(){
22     double pd = dis(p1,o);
23     if(pd < eps){
24         printf("%.7f\n",2 * r);
25         return;
26     }
27     p2 = change(p1);
28     q2 = change(q1);
29     Point f;
30     f.x = ( p2.x + q2.x ) /2;
31     f.y = ( p2.y + q2.y ) /2;
32     double fd = dis(f,o);
33     //cerr<<fd<<" "<<f.x<<" "<<f.y<<" "<<p2.x<<" "<<p2.y<<" "<<q2.x<<" "<<q2.y<<endl;
34     double ans;
35     if( r - fd > -eps){
36         //cerr<<"ok1"<<endl;
37         ans = dis(q2,p2);
38         ans *= pd/r;
39     }
40     else{
41         //cerr<<"ok2"<<endl;
42         Point D;
43         D.x = f.x * r / fd;
44         D.y = f.y * r / fd;
45         ans = 2 * dis(D,p1);
46     }
47     printf("%.7f\n",ans);
48 }
49 int main(){
50     int T; scanf("%d",&T);
51     o.x = o.y = 0;
52     while(T--){
53         scanf("%lf %lf %lf %lf %lf",&r,&p1.x,&p1.y,&q1.x,&q1.y);
54         solve();
55     }
56     return 0;
57 }
View Code

 

posted @ 2020-02-06 17:50  小布鞋  阅读(282)  评论(0编辑  收藏  举报