●UVA 10674 Tangents
题链:
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的更多相关文章
- UVa 10674 (求两圆公切线) Tangents
题意: 给出两个圆的圆心坐标和半径,求这两个圆的公切线切点的坐标及对应线段长度.若两圆重合,有无数条公切线则输出-1. 输出是按照一定顺序输出的. 分析: 首先情况比较多,要一一判断,不要漏掉. 如果 ...
- 一位学长的ACM总结(感触颇深)
发信人: fennec (fennec), 信区: Algorithm 标 题: acm 总结 by fennec 发信站: 吉林大学牡丹园站 (Wed Dec 8 16:27:55 2004) AC ...
- .Uva&LA部分题目代码
1.LA 5694 Adding New Machine 关键词:数据结构,线段树,扫描线(FIFO) #include <algorithm> #include <cstdio&g ...
- uva 1354 Mobile Computing ——yhx
aaarticlea/png;base64,iVBORw0KGgoAAAANSUhEUgAABGcAAANuCAYAAAC7f2QuAAAgAElEQVR4nOy9XUhjWbo3vu72RRgkF5
- UVA 10564 Paths through the Hourglass[DP 打印]
UVA - 10564 Paths through the Hourglass 题意: 要求从第一层走到最下面一层,只能往左下或右下走 问有多少条路径之和刚好等于S? 如果有的话,输出字典序最小的路径 ...
- UVA 11404 Palindromic Subsequence[DP LCS 打印]
UVA - 11404 Palindromic Subsequence 题意:一个字符串,删去0个或多个字符,输出字典序最小且最长的回文字符串 不要求路径区间DP都可以做 然而要字典序最小 倒过来求L ...
- UVA&&POJ离散概率与数学期望入门练习[4]
POJ3869 Headshot 题意:给出左轮手枪的子弹序列,打了一枪没子弹,要使下一枪也没子弹概率最大应该rotate还是shoot 条件概率,|00|/(|00|+|01|)和|0|/n谁大的问 ...
- UVA计数方法练习[3]
UVA - 11538 Chess Queen 题意:n*m放置两个互相攻击的后的方案数 分开讨论行 列 两条对角线 一个求和式 可以化简后计算 // // main.cpp // uva11538 ...
- 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 ...
随机推荐
- servlet线程同步问题-代码实现同步(转)
从servlet的生命周期中,我们知道,当第一次访问某个servlet后,该servlet的实例就会常驻 内存,以后再次访问该servlet就会访问同一个servlet实例,这样就带来多个用户去访问一 ...
- 数据结构与算法 —— 链表linked list(02)
我们继续来看链表的第二道题,来自于leetcode: 两数相加 给定两个非空链表来代表两个非负整数,位数按照逆序方式存储,它们的每个节点只存储单个数字.将这两数相加会返回一个新的链表. 你可以假设除了 ...
- WIN7 局域网共享打印机每次电脑重启后必须登录密码重新连接问题修复
第一步,WIN+R(或者开始->附件->运行)输入gpedit或gpedit.msc 进入 第二步:把这几个拒绝的Guest给删除掉,也可以只删除""拒绝从王洛访问这台 ...
- MySQL默认储存引擎修改
1.输入以下SQL语句查看当前储存引擎支持: SHOW ENGINES; 如图所示本机默认引擎为MyISAM: 2.若要修改引擎执行: ALTER TABLE 表名 ENGINE = 储存引擎名: 3 ...
- Spring Security 入门(1-2)Spring Security - 从 配置例子例子 开始我们的学习历程
1.Spring Security 的配置文件 我们需要为 Spring Security 专门建立一个 Spring 的配置文件,该文件就专门用来作为 Spring Security 的配置. &l ...
- IDE-Android Studio 导入Ecplise项目不改变结构
Android Studio 导入 Ecplise创建的android 项目 无导入 不修改目录结构 首先,Ecplise 原有目录结构创建的android项目一枚 Sept 1 . 打开项目 S ...
- 使用Java High Level REST Client操作elasticsearch
Java高级别REST客户端(The Java High Level REST Client)以后简称高级客户端,内部仍然是基于低级客户端.它提供了更多的API,接受请求对象作为参数并返回响应对象,由 ...
- Python/MySQL(三、pymysql使用)
Python/MySQL(三.pymysql使用) 所谓pymysql就是通过pycharm导入pymysql模块进行远程连接mysql服务端进行数据管理操作. 一.在pycharm中导入pymysq ...
- mysql基础练习题
一.表关系 请创建如下表,并创建相关约束 二.操作表 1.自行创建测试数据 /* Navicat MySQL Data Transfer Source Server : mysql5.7.1 Sour ...
- 字符串分割方法split()函数
>>> data = '1000,小甲鱼,男'>>> data.split(',')['1000', '小甲鱼', '男'] str.split('以什么为标志进行 ...