uva 12304

题意:要求解答6个关于圆的问题。
1.给出三角形坐标求外接圆
2.给出三角形坐标求内切圆
3.给出一个圆心和半径已知的圆,求过点(x,y)的所有和这个圆相切的直线
4.求所有和已知直线相切的过定点(x,y)的已知半径的圆的圆心
5.给出两个不平行的直线,求所有半径为r的同时和这两个直线相切的圆
6.给定两个相离的圆,求出所有和这两个圆外切的半径为r的圆。

比较恶心的计算几何模板题,直接模板吧。。。。

  1 #include<cstdio>
  2 #include<cmath>
  3 #include<cstring>
  4 #include<algorithm>
  5 #include<iostream>
  6 #include<memory.h>
  7 #include<cstdlib>
  8 #include<vector>
  9 #define clc(a,b) memset(a,b,sizeof(a))
 10 #define LL long long int
 11 #define up(i,x,y) for(i=x;i<=y;i++)
 12 #define w(a) while(a)
 13 using namespace std;
 14 const int inf=0x3f3f3f3f;
 15 const int N = 110;
 16 const int maxn = 50;
 17 const double eps = 1e-10;        //调到1e-6以上第4问就可以用delta判断切线,但《训练指南》建议,尽量不要调eps
 18 const double pi = acos(-1);
 19
 20 char type[maxn];
 21
 22 int dcmp(double x)
 23 {
 24     return fabs(x) < eps ? 0 : (x > 0 ? 1 : -1);
 25 }
 26
 27 struct Point
 28 {
 29     double x;
 30     double y;
 31
 32     Point(double x = 0, double y = 0):x(x), y(y) {}
 33
 34     bool operator < (const Point& e) const
 35     {
 36         return dcmp(x - e.x) < 0 || (dcmp(x - e.x) == 0 && dcmp(y - e.y) < 0);
 37     }
 38
 39     bool operator == (const Point& e) const
 40     {
 41         return dcmp(x - e.x) == 0 && dcmp(y - e.y) == 0;
 42     }
 43
 44     int read()
 45     {
 46         return scanf("%lf%lf", &x, &y);
 47     }
 48 } p[3];
 49
 50 typedef Point Vector;
 51
 52 Vector operator + (Point A, Point B)
 53 {
 54     return Vector(A.x + B.x, A.y + B.y);
 55 }
 56
 57 Vector operator - (Point A, Point B)
 58 {
 59     return Vector(A.x - B.x, A.y - B.y);
 60 }
 61
 62 Vector operator * (Point A, double p)
 63 {
 64     return Vector(A.x * p, A.y * p);
 65 }
 66
 67 Vector operator / (Point A, double p)
 68 {
 69     return Vector(A.x / p, A.y / p);
 70 }
 71
 72 struct Line
 73 {
 74     Point p;
 75     Point v;
 76
 77     Line() {}
 78     Line(Point p, Point v):p(p), v(v) {}
 79
 80     int read()
 81     {
 82         return scanf("%lf%lf%lf%lf", &p.x, &p.y, &v.x, &v.y);
 83     }
 84
 85     Point point(double t)
 86     {
 87         return p + v * t;
 88     }
 89 };
 90
 91 struct Circle
 92 {
 93     Point c;
 94     double r;
 95
 96     Circle() {}
 97     Circle(Point c, double r):c(c), r(r) {}
 98
 99     int read()
100     {
101         return scanf("%lf%lf%lf", &c.x, &c.y, &r);
102     }
103
104     Point point(double a)
105     {
106         return Point(c.x + r * cos(a), c.y + r * sin(a));
107     }
108 };
109
110 double Dot(Vector A, Vector B)
111 {
112     return A.x * B.x + A.y * B.y;
113 }
114
115 double Cross(Vector A, Vector B)
116 {
117     return A.x * B.y - B.x * A.y;
118 }
119
120 double Length(Vector A)
121 {
122     return sqrt(Dot(A, A));
123 }
124
125 Vector Rotate(Vector A, double rad)
126 {
127     return Vector(A.x * cos(rad) - A.y * sin(rad), A.x * sin(rad) + A.y * cos(rad));
128 }
129
130 Vector Normal(Vector A)
131 {
132     double L = Length(A);
133     return Vector(-A.y / L, A.x / L);
134 }
135
136 double DistanceToLine(Point P, Point A, Point B)        //点到直线的距离
137 {
138     Vector v1 = B - A;
139     Vector v2 = P - A;
140     return fabs(Cross(v1, v2) / Length(v1));
141 }
142
143 double angle(Vector v)      //求向量的极角
144 {
145     return atan2(v.y, v.x);
146 }
147
148 Point GetLineIntersection(Line l1, Line l2)         //求两直线的交点(前提:相交)
149 {
150     Vector u = l1.p - l2.p;
151     double t = Cross(l2.v, u) / Cross(l1.v, l2.v);
152     return l1.point(t);
153 }
154
155 int getLineCircleIntersection(Line l, Circle C, double& t1, double& t2, vector<Point>& sol)         //求直线与圆的交点
156 {
157     double a = l.v.x;
158     double b = l.p.x - C.c.x;
159     double c = l.v.y;
160     double d = l.p.y - C.c.y;
161     double e = a * a + c * c;
162     double f = 2 * (a * b + c * d);
163     double g = b * b + d * d - C.r * C.r;
164     double delta = f * f - 4 * e * g;
165     double dist = DistanceToLine(C.c, l.p, l.p+l.v);
166     if(dcmp(dist - C.r) == 0)       //相切,此处需特殊判断,不能用delta
167     {
168         t1 = t2 = -f / (2 * e);
169         sol.push_back(l.point(t1));
170         return 1;
171     }
172     if(dcmp(delta) < 0) return 0;       //相离
173     else        //相交
174     {
175         t1 = (-f - sqrt(delta)) / (2 * e);
176         sol.push_back(l.point(t1));
177         t2 = (-f + sqrt(delta)) / (2 * e);
178         sol.push_back(l.point(t2));
179         return 2;
180     }
181 }
182
183 int GetCircleCircleIntersection(Circle C1, Circle C2, vector<Point>& sol)       //求圆与圆的交点
184 {
185     double d = Length(C1.c - C2.c);
186     if(dcmp(d) == 0)
187     {
188         if(dcmp(C1.r - C2.r) == 0) return -1;       //两圆重合
189         return 0;       //同心圆但不重合
190     }
191     if(dcmp(C1.r + C2.r - d) < 0) return 0;     //外离
192     if(dcmp(fabs(C1.r - C2.r) - d) > 0) return 0;       //内含
193     double a = angle(C2.c - C1.c);
194     double da = acos((C1.r * C1.r + d * d - C2.r * C2.r) / (2 * C1.r * d));
195     Point p1 = C1.point(a + da);
196     Point p2 = C1.point(a - da);
197     sol.push_back(p1);
198     if(p1 == p2) return 1;      //外切
199     sol.push_back(p2);
200     return 2;
201 }
202
203 Circle CircumscribedCircle(Point p1, Point p2, Point p3)        //求三角形的外心
204 {
205     double Bx = p2.x - p1.x, By = p2.y - p1.y;
206     double Cx = p3.x - p1.x, Cy = p3.y - p1.y;
207     double D = 2 * (Bx * Cy - By * Cx);
208     double cx = (Cy * (Bx * Bx + By * By) - By * (Cx * Cx + Cy * Cy)) / D + p1.x;
209     double cy = (Bx * (Cx * Cx + Cy * Cy) - Cx * (Bx * Bx + By * By)) / D + p1.y;
210     Point p(cx, cy);
211     return Circle(p, Length(p1-p));
212 }
213
214 Circle InscribedCircle(Point p1, Point p2, Point p3)        //求三角形的内切圆
215 {
216     double a = Length(p3 - p2);
217     double b = Length(p3 - p1);
218     double c = Length(p2 - p1);
219     Point p = (p1 * a + p2 * b + p3 * c) / (a + b + c);
220     return Circle(p, DistanceToLine(p, p2, p3));
221 }
222
223 int TangentLineThroughPoint(Point p, Circle C, Vector *v)       //求点到圆的直线
224 {
225     Vector u = C.c - p;
226     double dist = Length(u);
227     if(dcmp(dist - C.r) < 0) return 0;
228     else if(dcmp(dist - C.r) < eps)
229     {
230         v[0] = Rotate(u, pi / 2);
231         return 1;
232     }
233     else
234     {
235         double ang = asin(C.r / dist);
236         v[0] = Rotate(u, ang);
237         v[1] = Rotate(u, -ang);
238         return 2;
239     }
240 }
241
242 void CircleThroughAPointAndTangentToALineWithRadius(Point p, Point p1, Point p2, double r)
243 {
244     Vector AB = p2 - p1;
245     Vector change1 = Rotate(AB, pi / 2) / Length(AB) * r;
246     Vector change2 = Rotate(AB, -pi / 2) / Length(AB) * r;
247     Line l1(p1 + change1, AB);
248     Line l2(p1 + change2, AB);
249     vector<Point> sol;
250     sol.clear();
251     double t1, t2;
252     int cnt1 = getLineCircleIntersection(l1, Circle(p, r), t1, t2, sol);
253     int cnt2 = getLineCircleIntersection(l2, Circle(p, r), t1, t2, sol);
254     int cnt = cnt1 + cnt2;
255     if(cnt) sort(sol.begin(), sol.end());
256     printf("[");
257     for(int i = 0; i < cnt; i++)
258     {
259         printf("(%.6f,%.6f)", sol[i].x, sol[i].y);
260         if(cnt == 2 && !i) printf(",");
261     }
262     puts("]");
263 }
264
265 void CircleTangentToTwoLinesWithRadius(Point A, Point B, Point C, Point D, double r)
266 {
267     Vector AB = B - A;
268     Vector change = Normal(AB) * r;
269     Point newA1 = A + change;
270     Point newA2 = A - change;
271     Vector CD = D - C;
272     Vector update = Normal(CD) * r;
273     Point newC1 = C + update;
274     Point newC2 = C - update;
275     Point p[5];
276     p[0] = GetLineIntersection(Line(newA1, AB), Line(newC1, CD));
277     p[1] = GetLineIntersection(Line(newA1, AB), Line(newC2, CD));
278     p[2] = GetLineIntersection(Line(newA2, AB), Line(newC1, CD));
279     p[3] = GetLineIntersection(Line(newA2, AB), Line(newC2, CD));
280     sort(p, p + 4);
281     printf("[");
282     printf("(%.6f,%.6f)", p[0].x, p[0].y);
283     for(int i = 1; i < 4; i++)
284     {
285         printf(",(%.6f,%.6f)", p[i].x, p[i].y);
286     }
287     puts("]");
288 }
289
290 void CircleTangentToTwoDisjointCirclesWithRadius(Circle C1, Circle C2, double r)
291 {
292     Vector CC = C2.c - C1.c;
293     double rdist = Length(CC);
294     if(dcmp(2 * r - rdist + C1.r + C2.r) < 0) puts("[]");
295     else if(dcmp(2 * r - rdist + C1.r + C2.r) == 0)
296     {
297         double ang = angle(CC);
298         Point A = C1.point(ang);
299         Point B = C2.point(ang + pi);
300         Point ret = (A + B) / 2;
301         printf("[(%.6f,%.6f)]\n", ret.x, ret.y);
302     }
303     else
304     {
305         Circle A = Circle(C1.c, C1.r + r);
306         Circle B = Circle(C2.c, C2.r + r);
307         vector<Point> sol;
308         sol.clear();
309         GetCircleCircleIntersection(A, B, sol);
310         sort(sol.begin(), sol.end());
311         printf("[(%.6f,%.6f),(%.6f,%.6f)]\n", sol[0].x, sol[0].y, sol[1].x, sol[1].y);
312     }
313 }
314
315 int main()
316 {
317     while(scanf("%s", type) == 1)
318     {
319         if(strcmp(type, "CircumscribedCircle") == 0)
320         {
321             Point p1, p2, p3;
322             p1.read();
323             p2.read();
324             p3.read();
325             Circle ret = CircumscribedCircle(p1, p2, p3);
326             printf("(%f,%f,%f)\n", ret.c.x, ret.c.y, ret.r);
327         }
328         else if(strcmp(type, "InscribedCircle") == 0)
329         {
330             Point p1, p2, p3;
331             p1.read();
332             p2.read();
333             p3.read();
334             Circle ret = InscribedCircle(p1, p2, p3);
335             printf("(%f,%f,%f)\n", ret.c.x, ret.c.y, ret.r);
336         }
337         else if(strcmp(type, "TangentLineThroughPoint") == 0)
338         {
339             Circle C;
340             Point p;
341             C.read();
342             p.read();
343             Vector v[3];
344             int cnt = TangentLineThroughPoint(p, C, v);
345             double ret[3];
346             for(int i = 0; i < cnt; i++)
347             {
348                 ret[i] = angle(v[i]);
349                 if(dcmp(ret[i] - pi) == 0) ret[i] = 0;
350                 if(dcmp(ret[i]) < 0) ret[i] += pi;
351             }
352             sort(ret, ret + cnt);
353             printf("[");
354             for(int i = 0; i < cnt; i++)
355             {
356                 printf("%.6f", ret[i] / pi * 180);
357                 if(cnt == 2 && !i) printf(",");
358             }
359             puts("]");
360         }
361         else if(strcmp(type, "CircleThroughAPointAndTangentToALineWithRadius") == 0)
362         {
363             Point p, p1, p2;
364             double r;
365             p.read();
366             p1.read();
367             p2.read();
368             scanf("%lf", &r);
369             CircleThroughAPointAndTangentToALineWithRadius(p, p1, p2, r);
370         }
371         else if(strcmp(type, "CircleTangentToTwoLinesWithRadius") == 0)
372         {
373             Point A, B, C, D;
374             double r;
375             A.read();
376             B.read();
377             C.read();
378             D.read();
379             scanf("%lf", &r);
380             CircleTangentToTwoLinesWithRadius(A, B, C, D, r);
381         }
382         else
383         {
384             Circle C1, C2;
385             double r;
386             C1.read();
387             C2.read();
388             scanf("%lf", &r);
389             CircleTangentToTwoDisjointCirclesWithRadius(C1, C2, r);
390         }
391     }
392     return 0;
393 }

时间: 2024-10-24 23:44:23

uva 12304的相关文章

uva 12304 - 2D Geometry 110 in 1!(几何)

题目链接:uva 12304 - 2D Geometry 110 in 1! 没什么好说的,根据操作直接处理. #include <cstdio> #include <cstring> #include <cmath> #include <vector> #include <algorithm> using namespace std; const double pi = 4 * atan(1); const double eps = 1e-9;

UVa 12304 (6个二维几何问题合集) 2D Geometry 110 in 1!

这个题能1A纯属运气,要是WA掉,可真不知道该怎么去调了. 题意: 这是完全独立的6个子问题.代码中是根据字符串的长度来区分问题编号的. 给出三角形三点坐标,求外接圆圆心和半径. 给出三角形三点坐标,求内切圆圆心和半径. 给出一个圆和一个定点,求过定点作圆的所有切线的倾角(0≤a<180°) 给出一个点和一条直线,求一个半径为r的过该点且与该直线相切的圆. 给出两条相交直线,求所有半径为r且与两直线都相切的圆. 给出两个相离的圆,求半径为r且与两圆都相切的圆. 分析: 写出三角形两边的垂直平分线

uva 12304(圆的相关函数模板)

题意:要求解答6个关于圆的问题. 1.给出三角形坐标求外接圆 2.给出三角形坐标求内切圆 3.给出一个圆心和半径已知的圆,求过点(x,y)的所有和这个圆相切的直线 4.求所有和已知直线相切的过定点(x,y)的已知半径的圆的圆心 5.给出两个不平行的直线,求所有半径为r的同时和这两个直线相切的圆 6.给定两个相离的圆,求出所有和这两个圆外切的半径为r的圆. 题解:花了一天做这个,就当整理模板吧. #include <cstdio> #include <cstring> #includ

UVA 12304 /// 圆的综合题 圆的模板

题目大意: ①给出三角形三个点,求三角形外接圆,求外接圆的圆心和半径. ②给出三角形三个点,求三角形内接圆,求内接圆的圆心和半径. ③给出一个圆,和一个点,求过该点的圆的切线与x轴的夹角(0<=angle<180): ④给出一条直线,一个点p,指定半径r,求经过点p的与直线相切的半径为r的圆: ⑤给出两条直线,求与这两条直线相切的圆: ⑥给出两个圆,求同时与这两个圆相切的圆: 贴一下圆的模板 带了一些注释 主要包括以下内容 // 求三角形abc的外接圆c(圆心.半径) C csC(P a,P

UVA-12304 2D Geometry 110 in 1! (有关圆的基本操作)

UVA-12304 2D Geometry 110 in 1! 该问题包含以下几个子问题 CircumscribedCircle x1 y1 x2 y2 x3 y3 : 三角形外接圆 InscribedCircle x1 y1 x2 y2 x3 y3: 三角形内接圆 TangentLineThroughPoint xc yc r xp yp 过一点做圆的切线 CircleThroughAPointAndTangentToALineWithRadius xp yp x1 y1 x2 y2 r:找到

UVA 562 Dividing coins --01背包的变形

01背包的变形. 先算出硬币面值的总和,然后此题变成求背包容量为V=sum/2时,能装的最多的硬币,然后将剩余的面值和它相减取一个绝对值就是最小的差值. 代码: #include <iostream> #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> using namespace std; #define N 50007 int c[102],d

UVA 10341 Solve It

Problem F Solve It Input: standard input Output: standard output Time Limit: 1 second Memory Limit: 32 MB Solve the equation: p*e-x + q*sin(x) + r*cos(x) + s*tan(x) + t*x2 + u = 0 where 0 <= x <= 1. Input Input consists of multiple test cases and te

UVA 11014 - Make a Crystal(容斥原理)

UVA 11014 - Make a Crystal 题目链接 题意:给定一个NxNxN的正方体,求出最多能选几个整数点.使得随意两点PQ不会使PQO共线. 思路:利用容斥原理,设f(k)为点(x, y, z)三点都为k的倍数的点的个数(要扣掉一个原点O).那么全部点就是f(1),之后要去除掉共线的,就是扣掉f(2), f(3), f(5)..f(n).n为素数.由于这些素数中包括了合数的情况,而且这些点必定与f(1)除去这些点以外的点共线,所以扣掉.可是扣掉后会扣掉一些反复的.比方f(6)在f

[UVa] Palindromes(401)

UVA - 401 Palindromes Time Limit: 3000MS   Memory Limit: Unknown   64bit IO Format: %lld & %llu Submit Status Description A regular palindrome is a string of numbers or letters that is the same forward as backward. For example, the string "ABCDED