UVA10674 Tangents
题意
分析
就是圆的切线的模板。
注意精度问题,排序的时候也不能直接写,被卡了好几次。
时间复杂度\(O(T)\)
代码
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<set>
#include<map>
#include<queue>
#include<stack>
#include<algorithm>
#include<bitset>
#include<cassert>
#include<ctime>
#include<cstring>
#define rg register
#define il inline
#define co const
template<class T>il T read()
{
rg T data=0;
rg int w=1;
rg char ch=getchar();
while(!isdigit(ch))
{
if(ch=='-')
w=-1;
ch=getchar();
}
while(isdigit(ch))
{
data=data*10+ch-'0';
ch=getchar();
}
return data*w;
}
template<class T>T read(T&x)
{
return x=read<T>();
}
using namespace std;
typedef long long ll;
co double eps=1e-10;
int dcmp(double x)
{
if(fabs(x)<eps)
return 0;
else
return x<0?-1:1;
}
struct Point
{
double x,y;
Point(double x=0,double y=0)
:x(x),y(y){}
bool operator<(co Point&rhs)co // edit 1
{
return dcmp(x-rhs.x)?x<rhs.x:y<rhs.y;
}
bool operator==(co Point&rhs)co
{
return dcmp(x-rhs.x)==0&&dcmp(y-rhs.y)==0;
}
double angle()
{
return atan2(y,x);
}
};
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*(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 Dot(Vector A,Vector B)
{
return A.x*B.x+A.y*B.y;
}
double Length(Vector A)
{
return sqrt(Dot(A,A));
}
double Angle(Vector A,Vector B)
{
return acos(Dot(A,B)/Length(A)/Length(B));
}
double Cross(Vector A,Vector B)
{
return A.x*B.y-A.y*B.x;
}
double Area2(Point A,Point B,Point C)
{
return Cross(B-A,C-A);
}
Vector Rotate(Vector A,double rad)
{
return Vector(A.x*cos(rad)-A.y*sin(rad),A.x*sin(rad)+A.y*cos(rad));
}
Vector Normal(Vector A)
{
double L=Length(A);
return Vector(-A.y/L,A.x/L);
}
Point LineLineIntersection(Point P,Vector v,Point Q,Vector w)
{
Vector u=P-Q;
double t=Cross(w,u)/Cross(v,w);
return P+v*t;
}
double DistanceToLine(Point P,Point A,Point B)
{
Vector v1=B-A,v2=P-A;
return fabs(Cross(v1,v2))/Length(v1);
}
double DistanceToSegment(Point P,Point A,Point B)
{
if(A==B)
return Length(P-A);
Vector v1=B-A,v2=P-A,v3=P-B;
if(dcmp(Dot(v1,v2))<0)
return Length(v2);
if(dcmp(Dot(v1,v3))>0)
return Length(v3);
return DistanceToLine(P,A,B);
}
Point PointLineProjection(Point P,Point A,Point B)
{
Vector v=B-A;
return A+v*(Dot(v,P-A)/Dot(v,v));
}
bool SegmentProperIntersection(Point a1,Point a2,Point b1,Point b2)
{
double c1=Cross(a2-a1,b1-a1),c2=Cross(a2-a1,b2-a1),
c3=Cross(b2-b1,a1-b1),c4=Cross(b2-b1,a2-b1);
return dcmp(c1)*dcmp(c2)<0&&dcmp(c3)*dcmp(c4)<0;
}
bool OnSegment(Point p,Point a1,Point a2)
{
return dcmp(Cross(a1-p,a2-p))==0&&dcmp(Dot(a1-p,a2-p))<0;
}
double PolygonArea(Point*p,int n)
{
double area=0;
for(int i=1;i<n-1;++i)
area+=Cross(p[i]-p[0],p[i+1]-p[0]);
return area/2;
}
struct Line
{
Point p;
Vector v;
Line(Point p,Vector v)
:p(p),v(v){}
Point point(double t)
{
return p+v*t;
}
};
struct Circle
{
Point c;
double r;
Circle(Point c=0,double r=0)
:c(c),r(r){}
Point point(double a)
{
return Point(c.x+cos(a)*r,c.y+sin(a)*r);
}
};
int LineCircleIntersection(Line L,Circle C,double&t1,double&t2,vector<Point>&sol)
{
double a=L.v.x,b=L.p.x-C.c.x,c=L.v.y,d=L.p.y-C.c.y;
double e=a*a+c*c,f=2*(a*b+c*d),g=b*b+d*d-C.r*C.r;
double delta=f*f-4*e*g;
if(dcmp(delta)<0)
return 0;
if(dcmp(delta)==0)
{
t1=t2=-f/(2*e);
sol.push_back(L.point(t1));
return 1;
}
t1=(-f-sqrt(delta))/(2*e);
t2=(-f+sqrt(delta))/(2*e);
sol.push_back(L.point(t1));
sol.push_back(L.point(t2));
return 2;
}
int CircleCircleIntersection(Circle C1,Circle C2,vector<Point>&sol)
{
double d=Length(C1.c-C2.c);
if(dcmp(d)==0)
{
if(dcmp(C1.r-C2.r)==0)
return -1;
return 0;
}
if(dcmp(C1.r+C2.r-d)<0)
return 0;
if(dcmp(fabs(C1.r-C2.r)-d)>0)
return 0;
double a=(C2.c-C1.c).angle();
double da=acos((C1.r*C1.r+d*d-C2.r*C2.r)/(2*C1.r*d));
Point p1=C1.point(a-da),p2=C1.point(a+da);
sol.push_back(p1);
if(p1==p2)
return 1;
sol.push_back(p2);
return 2;
}
co double PI=acos(-1);
int PointCircleTangent(Point p,Circle C,vector<Vector>&sol)
{
Vector u=C.c-p;
double dist=Length(u);
if(dcmp(dist-C.r)<0)
return 0;
if(dcmp(dist-C.r)==0)
{
sol.push_back(Rotate(u,PI/2));
return 1;
}
double ang=asin(C.r/dist);
sol.push_back(Rotate(u,-ang));
sol.push_back(Rotate(u,ang));
return 2;
}
int CircleCircleTangent(Circle A,Circle B,vector<pair<Point,Point> >&sol)
{
int cnt=0;
if(dcmp(A.r-B.r)<0) // notice the result here
swap(A,B);
double d=Length(A.c-B.c);
double rdiff=A.r-B.r;
double rsum=A.r+B.r;
if(dcmp(d-rdiff)<0)
return 0;
double base=(B.c-A.c).angle();
if(dcmp(d)==0&&dcmp(A.r-B.r)==0)
return -1;
if(dcmp(d-rdiff)==0)
{
sol.push_back(make_pair(A.point(base),B.point(base)));
++cnt;
return 1;
}
double ang=acos((A.r-B.r)/d);
sol.push_back(make_pair(A.point(base+ang),B.point(base+ang)));
++cnt;
sol.push_back(make_pair(A.point(base-ang),B.point(base-ang)));
++cnt;
if(dcmp(d-rsum)==0)
{
sol.push_back(make_pair(A.point(base),B.point(base+PI)));
++cnt;
}
else if(dcmp(d-rsum)>0)
{
double ang=acos((A.r+B.r)/d);
sol.push_back(make_pair(A.point(base+ang),B.point(base+ang+PI)));
++cnt;
sol.push_back(make_pair(A.point(base-ang),B.point(base-ang+PI)));
++cnt;
}
return cnt;
}
int main()
{
// freopen("UVA10674.in","r",stdin);
// freopen("UVA10674.out","w",stdout);
Circle A,B;
vector<pair<Point,Point> >sol;
while(1)
{
read(A.c.x);read(A.c.y);read(A.r);
read(B.c.x);read(B.c.y);read(B.r);
if(A.c.x==0&&A.c.y==0&&A.r==0&&
B.c.x==0&&B.c.y==0&&B.r==0)
break;
sol.clear();
int cnt=CircleCircleTangent(A,B,sol);
printf("%d\n",cnt);
if(cnt>0)
{
if(dcmp(A.r-B.r)<0)
for(int i=0;i<cnt;++i)
swap(sol[i].first,sol[i].second);
sort(sol.begin(),sol.end());
for(int i=0;i<cnt;++i)
{
printf("%.5lf %.5lf ",sol[i].first.x,sol[i].first.y);
printf("%.5lf %.5lf ",sol[i].second.x,sol[i].second.y);
printf("%.5lf\n",Length(sol[i].first-sol[i].second));
}
}
}
return 0;
}
UVA10674 Tangents的更多相关文章
- FZU 2213 Common Tangents(公切线)
Description 题目描述 Two different circles can have at most four common tangents. The picture below is a ...
- ●UVA 10674 Tangents
题链: https://vjudge.net/problem/UVA-10674 题解: 计算几何,求两个圆的公切线. <算法竞赛入门经典——训练指南>P266,讲得很清楚的. 大致是分为 ...
- FZU 2213——Common Tangents——————【两个圆的切线个数】
Problem 2213 Common Tangents Accept: 7 Submit: 8Time Limit: 1000 mSec Memory Limit : 32768 KB ...
- 福建省赛-- Common Tangents(数学几何)
Problem B Common Tangents Accept: 191 Submit: 608 Time Limit: 1000 mSec Memory Limit : 32768 K ...
- UVa 10674 (求两圆公切线) Tangents
题意: 给出两个圆的圆心坐标和半径,求这两个圆的公切线切点的坐标及对应线段长度.若两圆重合,有无数条公切线则输出-1. 输出是按照一定顺序输出的. 分析: 首先情况比较多,要一一判断,不要漏掉. 如果 ...
- FZU 2213 Common Tangents 第六届福建省赛
题目链接:http://acm.fzu.edu.cn/problem.php?pid=2213 题目大意:两个圆,并且知道两个圆的圆心和半径,求这两个圆共同的切线有多少条,若有无数条,输出-1,其他条 ...
- FZU Problem 2213 Common Tangents
其实是不太好意思往博客上放的,因为是一道巨水的题,但是我却错了一次,没有判断重合,放上还是为了警示自己,尽量不要在水题上罚时 #include<iostream> #include< ...
- Unity Cookie
1 在Unity里面,选择脚本单击左键打开 Sync Mono Development 这样就可以打开整个工程的脚本文件 进而才能在脚本中继续进行切换 Mesh MeshFilt ...
- OpenCASCADE Conic to BSpline Curves-Hyperbola
OpenCASCADE Conic to BSpline Curves-Hyperbola eryar@163.com Abstract. Rational Bezier Curve can repr ...
随机推荐
- 详解Linux系统下PXE服务器的部署过程
在大规模安装服务器时,需要批量自动化方法来安装服务器,来减少日常的工作量. 但是批量自动化安装服务器的基础是网络启动服务器(bootserver). 下面我们就介绍一下 网络启动服务器的 安装和配置方 ...
- Steema TeeChart Pro VCL FMX 2017.20 Full Suorce在Delphi XE10下的安装
一.首先将压缩包TeeChart Pro VCL FMX 2017.20 FS.rar解压到一个目录,比如 E:\Application\Steema TeeChart Pro VCL FMX 201 ...
- 重装window 7系统,从做一个u盘启动盘,到装系统,很不错
老毛桃U盘启动盘制作工具是现在最流行的U盘装系统和维护电脑的专用工具,一是制作简单,几乎100%支持所有U盘一键制作为启动盘,不必顾虑以前量产U盘考虑专用工具的问题.二是制作后工具功能强大,支持GHO ...
- Spring -- aop, 用Aspectj进行AOP开发
1. 概要 添加类库:aspectjrt.jar和aspectjweaver.jar 添加aop schema. 定义xml元素:<aop:aspectj-autoproxy> 编写jav ...
- python面向对象编程学习
python面向对象编程 基本概念理解 面向对象编程--Object Oriented Programming,简称OOP,是一种程序设计思想.OOP把对象作为程序的基本单元,一个对象包含了数据和操作 ...
- Confluence 6 配置系统属性
在这个页面中描述 Confluence 启动时如何设置 Java 属性和其他选项. 请查看 How to fix out of memory errors by increasing availabl ...
- 百度之星2017初赛A-1005-今夕何夕
今夕何夕 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submis ...
- zoj 3212 K-Nice(构造)
K-Nice Time Limit: 1 Second Memory Limit: 32768 KB Special Judge This is a super simple pr ...
- Elasticsearch: 权威指南(官方教程)
<Elasticsearch 权威指南>中文版 序言 前言 基础入门 深入搜索 处理人类语言 聚合 地理位置 数据建模 管理.监控和部署
- 【python】ConfigParser写入和读取配置文件
参照博客 http://www.cnblogs.com/TankXiao/p/3038350.html 配置文件格式: [section1] name = tank age = 28 [section ...