题意

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. 《网络攻防》Web安全基础实践

    20145224陈颢文 <网络攻防>Web安全基础实践 基础问题回答 SQL注入攻击原理,如何防御: 部分程序员在编写代码的时候,没有对用户输入数据的合法性进行判断,黑客利用这个bug在数 ...

  2. tyvj 1091 等差数列 dp

    P1091 等差数列 时间: 1000ms / 空间: 131072KiB / Java类名: Main 背景 广东汕头聿怀初中 Train#3 Problem 3 描述 等差数列的定义是一个数列S, ...

  3. 深入浅出TensorFlow(二):TensorFlow解决MNIST问题入门

    2017年2月16日,Google正式对外发布Google TensorFlow 1.0版本,并保证本次的发布版本API接口完全满足生产环境稳定性要求.这是TensorFlow的一个重要里程碑,标志着 ...

  4. 在myeclipse中安装svn

    首先下载site.zip,然后解压.在myeclipse的安装目录中的dropins文件夹中新建svn文件夹,把site中的features和plugins文件夹复制到svn中即可.然后重启Myecl ...

  5. 四十二 Python分布式爬虫打造搜索引擎Scrapy精讲—elasticsearch(搜索引擎)的mget和bulk批量操作

    注意:前面讲到的各种操作都是一次http请求操作一条数据,如果想要操作多条数据就会产生多次请求,所以就有了mget和bulk批量操作,mget和bulk批量操作是一次请求可以操作多条数据 1.mget ...

  6. 监控和审计IBM InfoSphere BigInsights和Cloudera Hadoop的访问权限

    http://www.ithov.com/server/124456.shtml 您也将学习一个仅适用于 IBM InfoSphere BigInsights 的快速启动监控实现. 大数据骚动主要集中 ...

  7. opencv:创建滑动条

    函数原型: ,); #include <opencv.hpp> using namespace cv; #define WINDOW_NAME "线性混合示例" // ...

  8. Lucene快速入门

    1. 什么是lucene lucene是Apache的一个全文检索工具,使用lucene能快速实现全文检索功能.Lucene是一个工具包,你可以调用它的函数, 但它不能独立运行,不单独对外提供服务. ...

  9. MVC框架中的值提供机制(三)

    在MVC框架中NameValueCollectionValueProvider采用一个NameValueCollection作为数据源,DictionnaryValueProvider的数据源类型自然 ...

  10. 下载并安装Prism5.0库 Download and Setup Prism Library 5.0 for WPF(英汉对照版)

    Learn what’s included in Prism 5.0 including the documentation, WPF code samples, and libraries. Add ...