题意:

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

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

分析:

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

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

 //#define LOCAL
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <vector>
using namespace std; const double PI = acos(-1.0);
const double EPS = 1e-;
struct Point
{
double x, y;
Point(double x=, double y=):x(x), y(y) {} };
typedef Point Vector;
Vector operator + (Vector A, Vector B)
{
return Vector(A.x+B.x, A.y+B.y);
}
Vector operator - (Vector A, Vector B)
{
return Vector(A.x-B.x, A.y-B.y);
}
Vector operator * (Vector A, double p)
{
return Vector(A.x*p, A.y*p);
}
Vector operator / (Vector A, double p)
{
return Vector(A.x/p, A.y/p);
}
double dcmp(double x)
{
if(fabs(x) < EPS) return ;
else return x < ? - : ;
}
bool operator < (const Vector& a, const Vector& b)
{
return dcmp(a.x-b.x) < || dcmp(a.x-b.x) == && dcmp(a.y-b.y) < ;
}
bool operator == (const Vector& a, const Vector& b)
{
return dcmp(a.x-b.x) == && dcmp(a.y-b.y) == ;
}
double Dot(Vector a, Vector b)
{
return a.x*b.x + a.y*b.y;
}
double Cross(Vector a, Vector b)
{
return a.x*b.y - a.y*b.x;
}
double Length(Vector a)
{
return sqrt(Dot(a, a));
}
struct Circle
{
double x, y, r;
Circle(double x, double y, double r):x(x), y(y), r(r) {}
Point point(double a)
{
return Point(x + r*cos(a), y + r*sin(a));
}
};
int getTangents(Circle A, Circle B, Point* a, Point* b)
{
int cnt = ;
if(A.r < B.r) { swap(A, B); swap(a, b); }
double d2 = (A.x-B.x)*(A.x-B.x) + (A.y-B.y)*(A.y-B.y);
double rdiff = A.r - B.r;
double rsum = A.r + B.r;
if(d2 < rdiff*rdiff) return ; //内含 double base = atan2(B.y-A.y, B.x-A.x);
if(dcmp(d2) == && dcmp(A.r - B.r) == ) return -; //重合
if(dcmp(d2 - rdiff*rdiff) == ) //内切
{
a[cnt] = A.point(base); b[cnt] = B.point(base); cnt++;
return ;
} //有外公切线
double ang = acos((A.r - B.r) / sqrt(d2));
a[cnt] = A.point(base + ang); b[cnt] = B.point(base + ang); cnt++;
a[cnt] = A.point(base - ang); b[cnt] = B.point(base - ang); cnt++;
if(dcmp(rsum*rsum - d2) == )
{//外切
a[cnt] = b[cnt] = A.point(base); cnt++;
}
else if(dcmp(d2 - rsum*rsum) > )
{
ang = acos((A.r + B.r) / sqrt(d2));
a[cnt] = A.point(base + ang); b[cnt] = B.point(PI + base + ang); cnt++;
a[cnt] = A.point(base - ang); b[cnt] = B.point(PI + base - ang); cnt++;
}
return cnt;
} int main(void)
{
#ifdef LOCAL
freopen("10674in.txt", "r", stdin);
#endif int x1, y1, r1, x2, y2, r2;
while(scanf("%d%d%d%d%d%d", &x1, &y1, &r1, &x2, &y2, &r2) == && r1 && r2)
{
Point a[], b[];
Circle C1(x1, y1, r1), C2(x2, y2, r2);
int n = getTangents(C1, C2, a, b);
printf("%d\n", n);
int p[] = {, , , };
for(int i = ; i < n; ++i)
for(int j = i+; j < n; ++j)
if(a[p[j]] < a[p[i]] || (a[p[j]] == a[p[i]] && b[p[j]] < b[p[i]])) swap(p[i], p[j]);
for(int i = ; i < n; ++i)
printf("%.5lf %.5lf %.5lf %.5lf %.5lf\n", a[p[i]].x, a[p[i]].y, b[p[i]].x, b[p[i]].y, Length(a[p[i]] - b[p[i]]));
} return ;
}

代码君

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

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

 //#define LOCAL
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <cmath>
using namespace std; struct Point
{
double x, y;
Point(double x=, double y=) :x(x),y(y) {}
};
typedef Point Vector;
const double EPS = 1e-;
Vector operator + (Vector A, Vector B) { return Vector(A.x + B.x, A.y + B.y); }
Vector operator - (Vector A, Vector B) { return Vector(A.x - B.x, A.y - B.y); }
Vector operator * (Vector A, double p) { return Vector(A.x*p, A.y*p); }
Vector operator / (Vector A, double p) { return Vector(A.x/p, A.y/p); }
bool operator < (const Point& a, const Point& b)
{ return a.x < b.x || (a.x == b.x && a.y < b.y); }
int dcmp(double x)
{ if(fabs(x) < EPS) return ; else return x < ? - : ; }
bool operator == (const Point& a, const Point& b)
{ return dcmp(a.x-b.x) == && dcmp(a.y-b.y) == ; }
double Dot(Vector A, Vector B)
{ return A.x*B.x + A.y*B.y; }
double Length(Vector A) { return sqrt(Dot(A, A)); } struct Circle
{
Point c; //Ô²ÐÄ
double r; //°ë¾¶
//Circle(Point c, double r):c(c), r(r) {}
Point point(double a)
{//Çó¶ÔÓ¦Ô²ÐĽǵĵã
return Point(c.x + r*cos(a), c.y + r*sin(a));
}
};
double angle(Vector v) { return atan2(v.y, v.x); }
const double PI = acos(-1.0); int getTangents(Circle A, Circle B, Point* a, Point* b)
{
int cnt = ;
if(A.r < B.r) { swap(A, B); swap(a, b); }
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);
double rdiff = A.r - B.r;
double rsum = A.r + B.r;
if(d2 < rdiff*rdiff) return ; //ÄÚº¬ double base = atan2(B.c.y-A.c.y, B.c.x-A.c.x);
if(dcmp(d2) == && dcmp(A.r-B.r) == ) return -; //Á½Ô²Öغϣ¬ÎÞÇî¶àÌõÇÐÏß
if(dcmp(d2 - rdiff*rdiff) == ) //ÄÚÇÐ
{
a[cnt] = A.point(base);
b[cnt] = B.point(base);
cnt++;
return ;
}
//ÓÐÍ⹫ÇÐÏß
double ang = acos((A.r-B.r) / sqrt(d2));
a[cnt] = A.point(base+ang); b[cnt] = B.point(base+ang); cnt++;
a[cnt] = A.point(base-ang); b[cnt] = B.point(base-ang); cnt++; if(dcmp(d2 - rsum*rsum) == ) //Ò»ÌõÄÚ¹«ÇÐÏß
{
a[cnt] = b[cnt] = A.point(base); cnt++;
}
else if(dcmp(d2 - rsum*rsum) > )
{
double ang = acos((A.r+B.r) / sqrt(d2));
a[cnt] = A.point(base+ang); b[cnt] = B.point(base+ang+PI); cnt++;
a[cnt] = A.point(base-ang); b[cnt] = B.point(base-ang+PI); cnt++;
}
//for(int i = 0; i < cnt; ++i)
// printf("%.5lf %.5lf %.5lf %.5lf\n", a[i].x, a[i].y, b[i].x, b[i].y);
return cnt;
} int main(void)
{
#ifdef LOCAL
freopen("10674in.txt", "r", stdin);
//freopen("10674out.txt", "w", stdout);
#endif int x1, y1, r1, x2, y2, r2;
while(scanf("%d%d%d%d%d%d", &x1, &y1, &r1, &x2, &y2, &r2) == && dcmp(r1) > )
{
Point a[], b[];
/*Point p1(x1, y1), p2(x2, y2);
Circle C1(p1, r1), C2(p2, r2);*/
Circle C1, C2;
C1.c.x=x1, C1.c.y=y1, C1.r=r1;
C2.c.x=x2, C2.c.y=y2, C2.r=r2;
int n = getTangents(C1, C2, a, b);
printf("%d\n", n);
if(n > )
{
int p[] = {, , , };
for(int i = ; i < n; ++i)
for(int j = i+; j < n; ++j)
if(a[p[j]] < a[p[i]] || (a[p[j]] == a[p[i]] && b[p[j]] < b[p[i]])) swap(p[i], p[j]);
for(int i = ; i < n; ++i)
printf("%.5lf %.5lf %.5lf %.5lf %.5lf\n", a[p[i]].x, a[p[i]].y, b[p[i]].x, b[p[i]].y, Length(a[p[i]] - b[p[i]]));
}
} return ;
}

WA掉的代码君

UVa 10674 (求两圆公切线) Tangents的更多相关文章

  1. POJ 2546 &amp; ZOJ 1597 Circular Area(求两圆相交的面积 模板)

    题目链接: POJ:http://poj.org/problem? id=2546 ZOJ:problemId=597" target="_blank">http: ...

  2. 求两圆相交部分面积(C++)

    已知两圆圆心坐标和半径,求相交部分面积: #include <iostream> using namespace std; #include<cmath> #include&l ...

  3. hdu5858 Hard problem(求两圆相交面积)

    题目传送门 Hard problem Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Other ...

  4. hdu 5120 (求两圆相交的面积

    题意:告诉你两个圆环,求圆环相交的面积. /* gyt Live up to every day */ #include<cstdio> #include<cmath> #in ...

  5. Gym-101915B Ali and Wi-Fi 计算几何 求两圆交点

    题面 题意:给你n个圆,每个圆有一个权值,你可以选择一个点,可以获得覆盖这个点的圆中,权值最大的m个的权值,问最多权值是多少 题解:好像是叙利亚的题....我们画画图就知道,我们要找的就是圆与圆交的那 ...

  6. 2D空间中求两圆的交点

    出处:https://stackoverflow.com/questions/19916880/sphere-sphere-intersection-c-3d-coordinates-of-colli ...

  7. java求两个圆相交坐标

    最近由于项目需要,根据两个圆函数求出相交的坐标.实现代码如下,另感谢两圆求交点算法实现Java代码,虽然他所贡献的代码中存在问题,但仍有借鉴意义. 1.两个圆相交的数学求法 在中学数学中我们知道,一个 ...

  8. ●UVA 10674 Tangents

    题链: https://vjudge.net/problem/UVA-10674 题解: 计算几何,求两个圆的公切线. <算法竞赛入门经典——训练指南>P266,讲得很清楚的. 大致是分为 ...

  9. GPS(2)关于位置的3个示例,实时获取GPS定位数据,求两个经纬点距离,邻近某个区域圆时警告

    实时获取GPS定位数据 import android.app.Activity; import android.content.Context; import android.location.Loc ...

随机推荐

  1. C# testJsonAsXMLNodeAttribute - XML& json & Collections - XmlNode, XmlElement, XmlAttribute,Dictionary,List

    testJsonAsXMLNodeAttribute using Newtonsoft.Json; using System; using System.Collections.Generic; us ...

  2. BZOJ 1854: [Scoi2010]游戏 无向图判环

    题目链接: 题目 1854: [Scoi2010]游戏 Time Limit: 5 Sec Memory Limit: 162 MB 问题描述 lxhgww最近迷上了一款游戏,在游戏里,他拥有很多的装 ...

  3. 【POJ】【2987】Firing

    网络流/最大权闭合子图 胡伯涛论文里有讲…… sigh……细节处理太伤心了,先是count和ans输出弄反了,改过来顺序时又忘了必须先算出来ans!要是不执行一下Dinic的话count就无意义了…… ...

  4. [原] perforce 获取本地最近更新的Changelist

    获取perforce客户端最后一次sync的changelist, 前提是中间没有任何代码提交: http://stackoverflow.com/questions/47007/determinin ...

  5. 配置java环境

    1.下载JDK http://www.oracle.com/technetwork/java/javase/downloads/jdk7-downloads-1880260.html 2.下载之后ne ...

  6. Ignore files which are already versioned

    If you accidentally added some files which should have been ignored, how do you get them out of vers ...

  7. hdu2013

    http://acm.hdu.edu.cn/showproblem.php?pid=2013 #include<iostream> #include<stdio.h> #inc ...

  8. QAQ高精度模板笔记√

    #include <cmath> #include <cstdio> #include <cstring> #include <iostream> #i ...

  9. Project Euler 83:Path sum: four ways 路径和:4个方向

    Path sum: four ways NOTE: This problem is a significantly more challenging version of Problem 81. In ...

  10. [@Controller]3 详解@CookieValue,@PathVariable,@RequestBody,@RequestHeader,@RequestParam

    [@Controller]3 详解@CookieValue,@PathVariable,@RequestBody,@RequestHeader,@RequestParam 转载:http://blog ...