题意

PDF

分析

就是圆的切线的模板。

注意精度问题,排序的时候也不能直接写,被卡了好几次。

时间复杂度\(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的更多相关文章

  1. FZU 2213 Common Tangents(公切线)

    Description 题目描述 Two different circles can have at most four common tangents. The picture below is a ...

  2. ●UVA 10674 Tangents

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

  3. FZU 2213——Common Tangents——————【两个圆的切线个数】

    Problem 2213 Common Tangents Accept: 7    Submit: 8Time Limit: 1000 mSec    Memory Limit : 32768 KB ...

  4. 福建省赛-- Common Tangents(数学几何)

    Problem B Common Tangents Accept: 191    Submit: 608 Time Limit: 1000 mSec    Memory Limit : 32768 K ...

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

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

  6. FZU 2213 Common Tangents 第六届福建省赛

    题目链接:http://acm.fzu.edu.cn/problem.php?pid=2213 题目大意:两个圆,并且知道两个圆的圆心和半径,求这两个圆共同的切线有多少条,若有无数条,输出-1,其他条 ...

  7. FZU Problem 2213 Common Tangents

    其实是不太好意思往博客上放的,因为是一道巨水的题,但是我却错了一次,没有判断重合,放上还是为了警示自己,尽量不要在水题上罚时 #include<iostream> #include< ...

  8. Unity Cookie

    1   在Unity里面,选择脚本单击左键打开 Sync Mono Development  这样就可以打开整个工程的脚本文件 进而才能在脚本中继续进行切换      Mesh    MeshFilt ...

  9. OpenCASCADE Conic to BSpline Curves-Hyperbola

    OpenCASCADE Conic to BSpline Curves-Hyperbola eryar@163.com Abstract. Rational Bezier Curve can repr ...

随机推荐

  1. 详解Linux系统下PXE服务器的部署过程

    在大规模安装服务器时,需要批量自动化方法来安装服务器,来减少日常的工作量. 但是批量自动化安装服务器的基础是网络启动服务器(bootserver). 下面我们就介绍一下 网络启动服务器的 安装和配置方 ...

  2. 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 ...

  3. 重装window 7系统,从做一个u盘启动盘,到装系统,很不错

    老毛桃U盘启动盘制作工具是现在最流行的U盘装系统和维护电脑的专用工具,一是制作简单,几乎100%支持所有U盘一键制作为启动盘,不必顾虑以前量产U盘考虑专用工具的问题.二是制作后工具功能强大,支持GHO ...

  4. Spring -- aop, 用Aspectj进行AOP开发

    1. 概要 添加类库:aspectjrt.jar和aspectjweaver.jar 添加aop schema. 定义xml元素:<aop:aspectj-autoproxy> 编写jav ...

  5. python面向对象编程学习

    python面向对象编程 基本概念理解 面向对象编程--Object Oriented Programming,简称OOP,是一种程序设计思想.OOP把对象作为程序的基本单元,一个对象包含了数据和操作 ...

  6. Confluence 6 配置系统属性

    在这个页面中描述 Confluence 启动时如何设置 Java 属性和其他选项. 请查看 How to fix out of memory errors by increasing availabl ...

  7. 百度之星2017初赛A-1005-今夕何夕

    今夕何夕 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submis ...

  8. zoj 3212 K-Nice(构造)

    K-Nice Time Limit: 1 Second      Memory Limit: 32768 KB      Special Judge This is a super simple pr ...

  9. Elasticsearch: 权威指南(官方教程)

    <Elasticsearch 权威指南>中文版 序言 前言 基础入门 深入搜索 处理人类语言 聚合 地理位置 数据建模 管理.监控和部署

  10. 【python】ConfigParser写入和读取配置文件

    参照博客 http://www.cnblogs.com/TankXiao/p/3038350.html 配置文件格式: [section1] name = tank age = 28 [section ...