zoukankan      html  css  js  c++  java
  • UVa 10674 (求两圆公切线) Tangents

    题意:

    给出两个圆的圆心坐标和半径,求这两个圆的公切线切点的坐标及对应线段长度。若两圆重合,有无数条公切线则输出-1.

    输出是按照一定顺序输出的。

    分析:

    首先情况比较多,要一一判断,不要漏掉。

    如果高中的那点老底还在的话,代码还是很好理解的。

      1 //#define LOCAL
      2 #include <cstdio>
      3 #include <cstring>
      4 #include <algorithm>
      5 #include <cmath>
      6 #include <vector>
      7 using namespace std;
      8 
      9 const double PI = acos(-1.0);
     10 const double EPS = 1e-8;
     11 struct Point
     12 {
     13     double x, y;
     14     Point(double x=0, double y=0):x(x), y(y) {}
     15 
     16 };
     17 typedef Point Vector;
     18 Vector operator + (Vector A, Vector B)
     19 {
     20     return Vector(A.x+B.x, A.y+B.y);
     21 }
     22 Vector operator - (Vector A, Vector B)
     23 {
     24     return Vector(A.x-B.x, A.y-B.y);
     25 }
     26 Vector operator * (Vector A, double p)
     27 {
     28     return Vector(A.x*p, A.y*p);
     29 }
     30 Vector operator / (Vector A, double p)
     31 {
     32     return Vector(A.x/p, A.y/p);
     33 }
     34 double dcmp(double x)
     35 {
     36     if(fabs(x) < EPS)    return 0;
     37     else return x < 0 ? -1 : 1;
     38 }
     39 bool operator < (const Vector& a, const Vector& b)
     40 {
     41     return dcmp(a.x-b.x) < 0 || dcmp(a.x-b.x) == 0 && dcmp(a.y-b.y) < 0;
     42 }
     43 bool operator == (const Vector& a, const Vector& b)
     44 {
     45     return dcmp(a.x-b.x) == 0 && dcmp(a.y-b.y) == 0;
     46 }
     47 double Dot(Vector a, Vector b)
     48 {
     49     return a.x*b.x + a.y*b.y;
     50 }
     51 double Cross(Vector a, Vector b)
     52 {
     53     return a.x*b.y - a.y*b.x;
     54 }
     55 double Length(Vector a)
     56 {
     57     return sqrt(Dot(a, a));
     58 }
     59 struct Circle
     60 {
     61     double x, y, r;
     62     Circle(double x, double y, double r):x(x), y(y), r(r) {}
     63     Point point(double a)
     64     {
     65         return Point(x + r*cos(a), y + r*sin(a));
     66     }
     67 };
     68 int getTangents(Circle A, Circle B, Point* a, Point* b)
     69 {
     70     int cnt = 0;
     71     if(A.r < B.r)    { swap(A, B); swap(a, b); }
     72     double d2 = (A.x-B.x)*(A.x-B.x) + (A.y-B.y)*(A.y-B.y);
     73     double rdiff = A.r - B.r;
     74     double rsum = A.r + B.r;
     75     if(d2 < rdiff*rdiff)    return 0;    //内含
     76 
     77     double base = atan2(B.y-A.y, B.x-A.x);
     78     if(dcmp(d2) == 0 && dcmp(A.r - B.r) == 0)    return -1; //重合
     79     if(dcmp(d2 - rdiff*rdiff) == 0)    //内切
     80     {
     81         a[cnt] = A.point(base); b[cnt] = B.point(base); cnt++;
     82         return 1;
     83     }
     84 
     85     //有外公切线
     86     double ang = acos((A.r - B.r) / sqrt(d2));
     87     a[cnt] = A.point(base + ang); b[cnt] = B.point(base + ang); cnt++;
     88     a[cnt] = A.point(base - ang); b[cnt] = B.point(base - ang); cnt++;
     89     if(dcmp(rsum*rsum - d2) == 0)
     90     {//外切
     91         a[cnt] = b[cnt] = A.point(base); cnt++;
     92     }
     93     else if(dcmp(d2 - rsum*rsum) > 0)
     94     {
     95         ang = acos((A.r + B.r) / sqrt(d2));
     96         a[cnt] = A.point(base + ang); b[cnt] = B.point(PI + base + ang); cnt++;
     97         a[cnt] = A.point(base - ang); b[cnt] = B.point(PI + base - ang); cnt++;
     98     }
     99     return cnt;
    100 }
    101 
    102 int main(void)
    103 {
    104     #ifdef    LOCAL
    105         freopen("10674in.txt", "r", stdin);
    106     #endif
    107     
    108     int x1, y1, r1, x2, y2, r2;
    109     while(scanf("%d%d%d%d%d%d", &x1, &y1, &r1, &x2, &y2, &r2) == 6 && r1 && r2)
    110     {
    111         Point a[4], b[4];
    112         Circle C1(x1, y1, r1), C2(x2, y2, r2);
    113         int n = getTangents(C1, C2, a, b);
    114         printf("%d
    ", n);
    115         int p[4] = {0, 1, 2, 3};
    116         for(int i = 0; i < n; ++i)
    117             for(int j = i+1; j < n; ++j)
    118                 if(a[p[j]] < a[p[i]] || (a[p[j]] == a[p[i]] && b[p[j]] < b[p[i]]))    swap(p[i], p[j]);
    119         for(int i = 0; i < n; ++i)
    120             printf("%.5lf %.5lf %.5lf %.5lf %.5lf
    ", a[p[i]].x, a[p[i]].y, b[p[i]].x, b[p[i]].y, Length(a[p[i]] - b[p[i]]));
    121     }
    122 
    123     return 0;
    124 }
    代码君

    写的第一份,样例过,自己随机生成的1000组数据和lrj的代码对比,输出也是一模一样的,可就是无线WA。

    这里还是贴一下这份“神奇”的代码吧,也许日后能发现这个隐藏的错误。

      1 //#define LOCAL
      2 #include <cstdio>
      3 #include <cstring>
      4 #include <algorithm>
      5 #include <vector>
      6 #include <cmath>
      7 using namespace std;
      8 
      9 struct Point
     10 {
     11     double x, y;
     12     Point(double x=0, double y=0) :x(x),y(y) {}
     13 };
     14 typedef Point Vector;
     15 const double EPS = 1e-8;
     16 Vector operator + (Vector A, Vector B)    { return Vector(A.x + B.x, A.y + B.y); }
     17 Vector operator - (Vector A, Vector B)    { return Vector(A.x - B.x, A.y - B.y); }
     18 Vector operator * (Vector A, double p)    { return Vector(A.x*p, A.y*p); }
     19 Vector operator / (Vector A, double p)    { return Vector(A.x/p, A.y/p); }
     20 bool operator < (const Point& a, const Point& b)
     21 { return a.x < b.x || (a.x == b.x && a.y < b.y); }
     22 int dcmp(double x)
     23 { if(fabs(x) < EPS) return 0; else return x < 0 ? -1 : 1; }
     24 bool operator == (const Point& a, const Point& b)
     25 { return dcmp(a.x-b.x) == 0 && dcmp(a.y-b.y) == 0; }
     26 double Dot(Vector A, Vector B)
     27 { return A.x*B.x + A.y*B.y; }
     28 double Length(Vector A)    { return sqrt(Dot(A, A)); }
     29 
     30 struct Circle
     31 {
     32     Point c;    //Ô²ÐÄ
     33     double r;    //°ë¾¶
     34     //Circle(Point c, double r):c(c), r(r)    {}
     35     Point point(double a)
     36     {//Çó¶ÔÓ¦Ô²ÐĽǵĵã
     37         return Point(c.x + r*cos(a), c.y + r*sin(a));
     38     }
     39 };
     40 double angle(Vector v)    { return atan2(v.y, v.x); }
     41 const double PI = acos(-1.0); 
     42 
     43 int getTangents(Circle A, Circle B, Point* a, Point* b)
     44 {
     45     int cnt = 0;
     46     if(A.r < B.r)    { swap(A, B); swap(a, b); }
     47     double d2 = (A.c.x-B.c.x)*(A.c.x-B.c.x) + (A.c.y-B.c.y)*(A.c.y-B.c.y);
     48     double rdiff = A.r - B.r;
     49     double rsum  = A.r + B.r;
     50     if(d2 < rdiff*rdiff)    return 0;    //ÄÚº¬
     51 
     52     double base = atan2(B.c.y-A.c.y, B.c.x-A.c.x);
     53     if(dcmp(d2) == 0 && dcmp(A.r-B.r) == 0)    return -1;    //Á½Ô²Öغϣ¬ÎÞÇî¶àÌõÇÐÏß
     54     if(dcmp(d2 - rdiff*rdiff) == 0)                //ÄÚÇÐ
     55     {
     56         a[cnt] = A.point(base);
     57         b[cnt] = B.point(base);
     58         cnt++;
     59         return 1;
     60     }
     61     //ÓÐÍ⹫ÇÐÏß
     62     double ang = acos((A.r-B.r) / sqrt(d2));
     63     a[cnt] = A.point(base+ang); b[cnt] = B.point(base+ang); cnt++;
     64     a[cnt] = A.point(base-ang); b[cnt] = B.point(base-ang); cnt++;
     65     
     66     if(dcmp(d2 - rsum*rsum) == 0)    //Ò»ÌõÄÚ¹«ÇÐÏß
     67     {
     68         a[cnt] = b[cnt] = A.point(base); cnt++;
     69     }
     70     else if(dcmp(d2 - rsum*rsum) > 0)
     71     {
     72         double ang = acos((A.r+B.r) / sqrt(d2));
     73         a[cnt] = A.point(base+ang); b[cnt] = B.point(base+ang+PI); cnt++;
     74         a[cnt] = A.point(base-ang); b[cnt] = B.point(base-ang+PI); cnt++;
     75     }
     76     //for(int i = 0; i < cnt; ++i)
     77       //    printf("%.5lf %.5lf %.5lf %.5lf
    ", a[i].x, a[i].y, b[i].x, b[i].y);
     78     return cnt;
     79 }
     80 
     81 int main(void)
     82 {
     83     #ifdef    LOCAL
     84         freopen("10674in.txt", "r", stdin);
     85         //freopen("10674out.txt", "w", stdout);
     86     #endif
     87 
     88     int x1, y1, r1, x2, y2, r2;
     89     while(scanf("%d%d%d%d%d%d", &x1, &y1, &r1, &x2, &y2, &r2) == 6 && dcmp(r1) > 0)
     90     {
     91         Point a[10], b[10];
     92         /*Point p1(x1, y1), p2(x2, y2);
     93         Circle C1(p1, r1), C2(p2, r2);*/
     94         Circle C1, C2;
     95         C1.c.x=x1, C1.c.y=y1, C1.r=r1;
     96         C2.c.x=x2, C2.c.y=y2, C2.r=r2;
     97         int n = getTangents(C1, C2, a, b);
     98         printf("%d
    ", n);
     99         if(n > 0)
    100         {
    101             int p[4] = {0, 1, 2, 3};
    102             for(int i = 0; i < n; ++i)
    103                 for(int j = i+1; j < n; ++j)
    104                     if(a[p[j]] < a[p[i]] || (a[p[j]] == a[p[i]] && b[p[j]] < b[p[i]]))    swap(p[i], p[j]);
    105             for(int i = 0; i < n; ++i)
    106                 printf("%.5lf %.5lf %.5lf %.5lf %.5lf
    ", a[p[i]].x, a[p[i]].y, b[p[i]].x, b[p[i]].y, Length(a[p[i]] - b[p[i]]));
    107         }
    108     }
    109 
    110     return 0;
    111 }
    WA掉的代码君
  • 相关阅读:
    C#:类的学习
    SilverLight xaml页面跳转方法
    C#对象生命周期(转载)
    jquery常用的方法
    关于Java日期简单应用
    Compilingphpwithcrypt()
    SSI使用详解
    实例解析:从IIS的ASP迁移到APACHE的PHP
    三步搞定phpwind的静态化部署
    Informix Dynamic Server 中的分布式事务
  • 原文地址:https://www.cnblogs.com/AOQNRMGYXLMV/p/4027743.html
Copyright © 2011-2022 走看看