题链:

https://vjudge.net/problem/UVA-10674

题解:

计算几何,求两个圆的公切线。

《算法竞赛入门经典——训练指南》P266,讲得很清楚的。

大致是分为6种情况——内含,重合,内切,相交,外切,相离这六个情况去处理,

找到共通点,便于代码编写。

代码:

#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const double eps=1e-8;
const double Pi=acos(-1);
int sign(double x){
if(fabs(x)<=eps) return 0;
return x<0?-1:1;
}
struct Point{
double x,y;
Point(double _x=0,double _y=0):x(_x),y(_y){}
void Read(){scanf("%lf%lf",&x,&y);}
};
struct Circle{
Point o; double r;
Point GP(double a){//Get_Point
return Point(o.x+r*cos(a),o.y+r*sin(a));
}
}C1,C2;
struct Intersect{
Point P[2];
bool operator <(const Intersect &rtm) const{
return sign(P[0].x-rtm.P[0].x)<0||(sign(P[0].x-rtm.P[0].x)==0&&sign(P[0].y-rtm.P[0].y)<0);
}
}ANS[7];
typedef Point Vector;
Vector operator + (Vector A,Vector B){return Vector(A.x+B.x,A.y+B.y);}
Vector operator - (Point A,Point B){return Vector(A.x-B.x,A.y-B.y);}
Vector operator * (Point A,double p){return Vector(A.x*p,A.y*p);}
double operator ^ (Vector A,Vector B){return A.x*B.y-A.y*B.x;}
double operator * (Vector A,Vector B){return A.x*B.x+A.y*B.y;}
double GPA(Vector A){//Get_Polar_Angle
return atan2(A.y,A.x);
}
double GL(Vector A){//Get_Length
return sqrt(A*A);
}
int GCCI(Circle A,Circle B){//Get_Circle_Circle_Intersection
int cnt=0,a=0,b=1;
if(A.r<B.r) swap(A,B),swap(a,b);
Vector u=B.o-A.o;
double d=GL(u),rdec=A.r-B.r,radd=A.r+B.r;
if(sign(d-rdec)<0) return 0; //内含
if(sign(d)==0&&A.r==B.r) return -1; //重合,无线多
double base=GPA(u);
if(sign(d-rdec)==0){ //内切
ANS[++cnt].P[a]=A.GP(base); ANS[cnt].P[b]=B.GP(base);
return cnt;
}
double da=acos((A.r-B.r)/d); //2条外公切线
ANS[++cnt].P[a]=A.GP(base+da); ANS[cnt].P[b]=B.GP(base+da);
ANS[++cnt].P[a]=A.GP(base-da); ANS[cnt].P[b]=B.GP(base-da);
if(sign(d-radd)==0){ //1条内公切线
ANS[++cnt].P[a]=A.GP(base); ANS[cnt].P[b]=B.GP(base+Pi);
}
else if(sign(d-radd)>0){ //2条内公切线
da=acos((A.r+B.r)/d);
ANS[++cnt].P[a]=A.GP(base+da); ANS[cnt].P[b]=B.GP(base+da+Pi);
ANS[++cnt].P[a]=A.GP(base-da); ANS[cnt].P[b]=B.GP(base-da+Pi);
}
return cnt;
}
int main(){
int cnt;
while(1){
C1.o.Read(); scanf("%lf",&C1.r);
C2.o.Read(); scanf("%lf",&C2.r);
if(!C1.o.x&&!C1.o.y&&!C1.r&&!C2.o.x&&!C2.o.y&&!C2.r) break;
cnt=GCCI(C1,C2);
printf("%d\n",cnt);
if(cnt<=0) continue;
sort(ANS+1,ANS+cnt+1);
for(int i=1;i<=cnt;i++){
printf("%.5lf %.5lf %.5lf %.5lf %.5lf\n",ANS[i].P[0].x,ANS[i].P[0].y,ANS[i].P[1].x,ANS[i].P[1].y,GL(ANS[i].P[1]-ANS[i].P[0]));
} }
return 0;
}

  

●UVA 10674 Tangents的更多相关文章

  1. UVa 10674 (求两圆公切线) Tangents

    题意: 给出两个圆的圆心坐标和半径,求这两个圆的公切线切点的坐标及对应线段长度.若两圆重合,有无数条公切线则输出-1. 输出是按照一定顺序输出的. 分析: 首先情况比较多,要一一判断,不要漏掉. 如果 ...

  2. 一位学长的ACM总结(感触颇深)

    发信人: fennec (fennec), 信区: Algorithm 标 题: acm 总结 by fennec 发信站: 吉林大学牡丹园站 (Wed Dec 8 16:27:55 2004) AC ...

  3. .Uva&LA部分题目代码

    1.LA 5694 Adding New Machine 关键词:数据结构,线段树,扫描线(FIFO) #include <algorithm> #include <cstdio&g ...

  4. uva 1354 Mobile Computing ——yhx

    aaarticlea/png;base64,iVBORw0KGgoAAAANSUhEUgAABGcAAANuCAYAAAC7f2QuAAAgAElEQVR4nOy9XUhjWbo3vu72RRgkF5

  5. UVA 10564 Paths through the Hourglass[DP 打印]

    UVA - 10564 Paths through the Hourglass 题意: 要求从第一层走到最下面一层,只能往左下或右下走 问有多少条路径之和刚好等于S? 如果有的话,输出字典序最小的路径 ...

  6. UVA 11404 Palindromic Subsequence[DP LCS 打印]

    UVA - 11404 Palindromic Subsequence 题意:一个字符串,删去0个或多个字符,输出字典序最小且最长的回文字符串 不要求路径区间DP都可以做 然而要字典序最小 倒过来求L ...

  7. UVA&&POJ离散概率与数学期望入门练习[4]

    POJ3869 Headshot 题意:给出左轮手枪的子弹序列,打了一枪没子弹,要使下一枪也没子弹概率最大应该rotate还是shoot 条件概率,|00|/(|00|+|01|)和|0|/n谁大的问 ...

  8. UVA计数方法练习[3]

    UVA - 11538 Chess Queen 题意:n*m放置两个互相攻击的后的方案数 分开讨论行 列 两条对角线 一个求和式 可以化简后计算 // // main.cpp // uva11538 ...

  9. UVA数学入门训练Round1[6]

    UVA - 11388 GCD LCM 题意:输入g和l,找到a和b,gcd(a,b)=g,lacm(a,b)=l,a<b且a最小 g不能整除l时无解,否则一定g,l最小 #include &l ...

随机推荐

  1. bzoj千题计划251:bzoj3672: [Noi2014]购票

    http://www.lydsy.com/JudgeOnline/problem.php?id=3672 法一:线段树维护可持久化单调队列维护凸包 斜率优化DP 设dp[i] 表示i号点到根节点的最少 ...

  2. 申请JetBrains学生免费注册码

    1.申请.edu.*后缀的邮箱 从某个知乎用户上面得到了两个可以申请的后缀edu的邮箱 上海交通大学校友统一身份认证:https://register.alumni.sjtu.edu.cn/alumn ...

  3. python使用tesseract-ocr完成验证码识别(安装部分)

    一.tesseract-ocr安装 Ubuntu版本: 1.tesseract-ocr安装 sudo apt-get install tesseract-ocr 2.pytesseract安装 sud ...

  4. .net mvc 利用分部视图局部刷新.

    页面利于$.Ajax: $(function(){ $("#btnpartview").click(function () { var model = []; model.push ...

  5. 流程控制语句(MySQL/MariaDB )

    本文目录:1.BEGIN...END2.true和false3.if结构4.case结构5.loop.leave和iterate6.repeat循环7.while循环 MySQL/MariaDB中的符 ...

  6. H5新特性之webWorker

    众所周知javascript是单线程语言,这就是js开发难度较低的原因了,因为不需要解决多线程的资源共享问题(例如死锁),但是单线程性能并不好,因此多了一个webWorker实现js的多进程来提升js ...

  7. js判断IE浏览器版本(IE8及以下)

    var DEFAULT_VERSION = 8.0; var ua = navigator.userAgent.toLowerCase(); var isIE = ua.indexOf("m ...

  8. Python内置函数(18)——bin

    英文文档: bin(x) Convert an integer number to a binary string. The result is a valid Python expression. ...

  9. angluarjs2入门学习资源

    http://www.runoob.com/angularjs2/angularjs2-tutorial.htmlhttps://segmentfault.com/a/1190000008423981 ...

  10. HTML初识

    HTML初识 web服务本质 import socket def main(): sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) so ...