计算几何(AIZU CGL一览)

#include<bits/stdc++.h>
#define mm(a,b) memset(a,b,sizeof(a))
#define ACCELERATE (ios::sync_with_stdio(false),cin.tie(0))
#define pii pair<int,int>
#define pdd pair<double,double>
#define pll pair<long long,long long>
#define mp make_pair
#define pb push_back
#define fi first
#define se second
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
#define per(i,a,b) for(int i=(a);i>=(b);i--)
#define rush() int T;scanf("%d",&T);while(T--)
#define debug(x) cout<<#x<<": "<<x<<endl
#define sc(a) scanf("%d",&a)
#define sc2(a,b) scanf("%d%d",&a,&b)
#define sc3(a,b,c) scanf("%d%d%d",&a,&b,&c)
#define pf(x) printf("%d\n",x)
#define pf2(x,y) printf("%d %d\n",x,y)
#define pf3(x,y,z) printf("%d %d %d\n",x,y,z)
#define all(x) (x).begin(),(x).end()
#define PI acos(-1.0)
#define E exp(1.0)
#define db double
#define ll long long
#define ld long double
#define ull unsigned long long
//#define io
using namespace std;
const int inf=0x3f3f3f3f;
const ll INF=0x3f3f3f3f3f3f3f3f;
//#define gc getchar
char buf[1<<21],*p1=buf,*p2=buf;
inline int gc(){return p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++;}
inline int read()
{
    int ret=0,f=0;char c=gc();
    while(!isdigit(c)){if(c=='-')f=1;c=gc();}
    while(isdigit(c)){ret=ret*10+c-48;c=gc();}
    if(f)return -ret;return ret;
}
const db EPS=1e-9;
inline int sign(db a){return a<-EPS?-1:a>EPS;}
inline int cmp(db a,db b){return sign(a-b);}
//点
struct P{
    db x,y;
    P(){}
    P(db _x,db _y):x(_x),y(_y){}
    P operator + (P p){return P(x+p.x,y+p.y);}
    P operator - (P p){return P(x-p.x,y-p.y);}
    P operator * (db k){return P(x*k,y*k);}
    P operator / (db k){return P(x/k,y/k);}
    db dot(P p){return x*p.x+y*p.y;}
    db det(P p){return x*p.y-y*p.x;}
    db distTo(P p){return (*this-p).abs();}
    db alpha(){return atan2(y,x);}
    void read(){cin>>x>>y;}
    void write(){cout<<"("<<x<<","<<y<<")"<<endl;}
    db abs(){return sqrt(abs2());}
    db abs2(){return x*x+y*y;}
    P rot90(){return P(-y,x);}
    P unit(){return *this/abs();}
    int quad(){return sign(y)==1||(sign(y)==0&&sign(x)>=0);}
    P rot(db an){return P(x*cos(an)-y*sin(an),x*sin(an)+y*cos(an));}
    bool operator < (P p)const{
        int c=cmp(x,p.x);
        if(c)return c==-1;
        return cmp(y,p.y)==-1;
    }
    bool operator == (P o)const{
        return cmp(x,o.x)==0&&cmp(y,o.y)==0;
    }
};
//极角排序
//if(a.quad()!=b.quad())return a.quad()<b.quad();
//else sign(a.det(b)==-1);
//线
struct L{ //ps[0] -> ps[1]
	P ps[2];
	P operator[](int i) const { return ps[i]; }
	P dir() { return ps[1] - ps[0]; }
	L (P a,P b) {
		ps[0]=a;
		ps[1]=b;
	}
	bool include(P p) { return sign((ps[1] - ps[0]).det(p - ps[0])) > 0; }
	L push(){ // push eps outward
		const double eps = 1e-8;
		P delta = (ps[1] - ps[0]).rot90().unit() * eps;
		return {ps[0] + delta, ps[1] + delta};
	}
};
#define cross(p1,p2,p3) ((p2.x-p1.x)*(p3.y-p1.y)-(p3.x-p1.x)*(p2.y-p1.y))
#define crossOp(p1,p2,p3) sign(cross(p1,p2,p3))
bool chkLL(P p1,P p2,P q1,P q2){
	db a1=cross(q1,q2,p1),a2=-cross(q1,q2,p2);
	return sign(a1+a2)!=0;
}
P isLL(P p1, P p2, P q1, P q2) {
	db a1 = cross(q1, q2, p1), a2 = -cross(q1, q2, p2);
	return (p1 * a2 + p2 * a1) / (a1 + a2);
}
P isLL(L l1,L l2){ return isLL(l1[0],l1[1],l2[0],l2[1]); }
//线段相交
bool intersect(db l1,db r1,db l2,db r2){
	if(l1>r1) swap(l1,r1); if(l2>r2) swap(l2,r2);
	return !( cmp(r1,l2) == -1 || cmp(r2,l1) == -1 );
}

bool isSS(P p1, P p2, P q1, P q2){
	return intersect(p1.x,p2.x,q1.x,q2.x) && intersect(p1.y,p2.y,q1.y,q2.y) &&
	crossOp(p1,p2,q1) * crossOp(p1,p2,q2) <= 0 && crossOp(q1,q2,p1)
			* crossOp(q1,q2,p2) <= 0;
}

bool isSS_strict(P p1, P p2, P q1, P q2){
	return crossOp(p1,p2,q1) * crossOp(p1,p2,q2) < 0 && crossOp(q1,q2,p1)
			* crossOp(q1,q2,p2) < 0;
}
//点在线段上的判定
bool isMiddle(db a, db m, db b) {
	return sign(a - m) == 0 || sign(b - m) == 0 || (a < m != b < m);
}

bool isMiddle(P a, P m, P b) {
	return isMiddle(a.x, m.x, b.x) && isMiddle(a.y, m.y, b.y);
}

bool onSeg(P p1, P p2, P q){
	return crossOp(p1,p2,q) == 0 && isMiddle(p1, q, p2);
}

bool onSeg_strict(P p1, P p2, P q){
	return crossOp(p1,p2,q) == 0 && sign((q-p1).dot(p1-p2)) * sign((q-p2).dot(p1-p2)) < 0;
}
//投影
P proj(P p1, P p2, P q) {
	P dir = p2 - p1;
	return p1 + dir * (dir.dot(q - p1) / dir.abs2());
}
//反射
P reflect(P p1, P p2, P q){
	return proj(p1,p2,q) * 2 - q;
}
//最近点
db nearest(P p1,P p2,P q){
	P h = proj(p1,p2,q);
	if(isMiddle(p1,h,p2))
		return q.distTo(h);
	return min(p1.distTo(q),p2.distTo(q));
}
//线线距离
db disSS(P p1, P p2, P q1, P q2){
	if(isSS(p1,p2,q1,q2)) return 0;
	return min(min(nearest(p1,p2,q1),nearest(p1,p2,q2)), min(nearest(q1,q2,p1),nearest(q1,q2,p2)));
}
//夹角
db rad(P p1,P p2){
	return atan2l(p1.det(p2),p1.dot(p2));
}

db incircle(P p1, P p2, P p3){
	db A = p1.distTo(p2);
	db B = p2.distTo(p3);
	db C = p3.distTo(p1);
	return sqrtl(A*B*C/(A+B+C));
}
//polygon
//多边形面积
db area(vector<P> ps){
	db ret = 0; rep(i,0,ps.size()-1) ret += ps[i].det(ps[(i+1)%ps.size()]);
	return ret/2;
}
//点包含
int contain(vector<P> ps, P p){ //2:inside,1:on_seg,0:outside
	int n = ps.size(), ret = 0;
	rep(i,0,n){
		P u=ps[i],v=ps[(i+1)%n];
		if(onSeg(u,v,p)) return 1;
		if(cmp(u.y,v.y)<=0) swap(u,v);
		if(cmp(p.y,u.y) >0 || cmp(p.y,v.y) <= 0) continue;
		ret ^= crossOp(p,u,v) > 0;
	}
	return ret*2;
}
//凸包
vector<P> convexHull(vector<P> ps) {
	int n = ps.size(); if(n <= 1) return ps;
	sort(ps.begin(), ps.end());
	vector<P> qs(n * 2); int k = 0;
	for (int i = 0; i < n; qs[k++] = ps[i++])
		while (k > 1 && crossOp(qs[k - 2], qs[k - 1], ps[i]) <= 0) --k;
	for (int i = n - 2, t = k; i >= 0; qs[k++] = ps[i--])
		while (k > t && crossOp(qs[k - 2], qs[k - 1], ps[i]) <= 0) --k;
	qs.resize(k - 1);
	return qs;
}

vector<P> convexHullNonStrict(vector<P> ps) {
	//caution: need to unique the Ps first
	int n = ps.size(); if(n <= 1) return ps;
	sort(ps.begin(), ps.end());
	vector<P> qs(n * 2); int k = 0;
	for (int i = 0; i < n; qs[k++] = ps[i++])
		while (k > 1 && crossOp(qs[k - 2], qs[k - 1], ps[i]) < 0) --k;
	for (int i = n - 2, t = k; i >= 0; qs[k++] = ps[i--])
		while (k > t && crossOp(qs[k - 2], qs[k - 1], ps[i]) < 0) --k;
	qs.resize(k - 1);
	return qs;
}
//点集直径
db convexDiameter(vector<P> ps){
	int n = ps.size(); if(n <= 1) return 0;
	int is = 0, js = 0; rep(k,1,n) is = ps[k]<ps[is]?k:is, js = ps[js] < ps[k]?k:js;
	int i = is, j = js;
	db ret = ps[i].distTo(ps[j]);
	do{
		if((ps[(i+1)%n]-ps[i]).det(ps[(j+1)%n]-ps[j]) >= 0)
			(++j)%=n;
		else
			(++i)%=n;
		ret = max(ret,ps[i].distTo(ps[j]));
	}while(i!=is || j!=js);
	return ret;
}

vector<P> convexCut(const vector<P>&ps, P q1, P q2) {
	vector<P> qs;
	int n = ps.size();
	rep(i,0,n){
		P p1 = ps[i], p2 = ps[(i+1)%n];
		int d1 = crossOp(q1,q2,p1), d2 = crossOp(q1,q2,p2);
		if(d1 >= 0) qs.pb(p1);
		if(d1 * d2 < 0) qs.pb(isLL(p1,p2,q1,q2));
	}
	return qs;
}

//min_dist

db min_dist(vector<P>&ps,int l,int r){
	if(r-l<=5){
		db ret = 1e100;
		rep(i,l,r) rep(j,l,i) ret = min(ret,ps[i].distTo(ps[j]));
		return ret;
	}
	int m = (l+r)>>1;
	db ret = min(min_dist(ps,l,m),min_dist(ps,m,r));
	vector<P> qs; rep(i,l,r) if(abs(ps[i].x-ps[m].x)<= ret) qs.pb(ps[i]);
	sort(qs.begin(), qs.end(),[](P a,P b) -> bool {return a.y<b.y; });
	rep(i,1,qs.size()) for(int j=i-1;j>=0&&qs[j].y>=qs[i].y-ret;--j)
		ret = min(ret,qs[i].distTo(qs[j]));
	return ret;
}

int type(P o1,db r1,P o2,db r2){
	db d = o1.distTo(o2);
	if(cmp(d,r1+r2) == 1) return 4;
	if(cmp(d,r1+r2) == 0) return 3;
	if(cmp(d,abs(r1-r2)) == 1) return 2;
	if(cmp(d,abs(r1-r2)) == 0) return 1;
	return 0;
}

vector<P> isCL(P o,db r,P p1,P p2){
	if (cmp(abs((o-p1).det(p2-p1)/p1.distTo(p2)),r)>0) return {};
	db x = (p1-o).dot(p2-p1), y = (p2-p1).abs2(), d = x * x - y * ((p1-o).abs2() - r*r);
	d = max(d,0.0); P m = p1 - (p2-p1)*(x/y), dr = (p2-p1)*(sqrt(d)/y);
	return {m-dr,m+dr}; //along dir: p1->p2
}

vector<P> isCC(P o1, db r1, P o2, db r2) { //need to check whether two circles are the same
	db d = o1.distTo(o2);
	if (cmp(d, r1 + r2) == 1) return {};
	if (cmp(d,abs(r1-r2))==-1) return {};
	d = min(d, r1 + r2);
	db y = (r1 * r1 + d * d - r2 * r2) / (2 * d), x = sqrt(r1 * r1 - y * y);
	P dr = (o2 - o1).unit();
	P q1 = o1 + dr * y, q2 = dr.rot90() * x;
	return {q1-q2,q1+q2};//along circle 1
}

vector<P> tanCP(P o, db r, P p) {
	db x = (p - o).abs2(), d = x - r * r;
	if (sign(d) <= 0) return {}; // on circle => no tangent
	P q1 = o + (p - o) * (r * r / x);
	P q2 = (p - o).rot90() * (r * sqrt(d) / x);
	return {q1-q2,q1+q2}; //counter clock-wise
}


vector<L> extanCC(P o1, db r1, P o2, db r2) {
	vector<L> ret;
	if (cmp(r1, r2) == 0) {
		P dr = (o2 - o1).unit().rot90() * r1;
		ret.pb(L(o1 + dr, o2 + dr)), ret.pb(L(o1 - dr, o2 - dr));
	} else {
		P p = (o2 * r1 - o1 * r2) / (r1 - r2);
		vector<P> ps = tanCP(o1, r1, p), qs = tanCP(o2, r2, p);
		rep(i,0,min(ps.size(),qs.size())) ret.pb(L(ps[i], qs[i])); //c1 counter-clock wise
	}
	return ret;
}

vector<L> intanCC(P o1, db r1, P o2, db r2) {
	vector<L> ret;
	P p = (o1 * r2 + o2 * r1) / (r1 + r2);
	vector<P> ps = tanCP(o1,r1,p), qs = tanCP(o2,r2,p);
	rep(i,0,min(ps.size(),qs.size())) ret.pb(L(ps[i], qs[i])); //c1 counter-clock wise
	return ret;
}

db areaCT(db r, P p1, P p2){
	vector<P> is = isCL(P(0,0),r,p1,p2);
	if(is.empty()) return r*r*rad(p1,p2)/2;
	bool b1 = cmp(p1.abs2(),r*r) == 1, b2 = cmp(p2.abs2(), r*r) == 1;
	if(b1 && b2){
		if(sign((p1-is[0]).dot(p2-is[0])) <= 0 &&
			sign((p1-is[0]).dot(p2-is[0])) <= 0)
		return r*r*(rad(p1,is[0]) + rad(is[1],p2))/2 + is[0].det(is[1])/2;
		else return r*r*rad(p1,p2)/2;
	}
	if(b1) return (r*r*rad(p1,is[0]) + is[0].det(p2))/2;
	if(b2) return (p1.det(is[1]) + r*r*rad(is[1],p2))/2;
	return p1.det(p2)/2;
}


P inCenter(P A, P B, P C) {
	double a = (B - C).abs(), b = (C - A).abs(), c = (A - B).abs();
	return (A * a + B * b + C * c) / (a + b + c);
}

P circumCenter(P a, P b, P c) {
	P bb = b - a, cc = c - a;
	double db = bb.abs2(), dc = cc.abs2(), d = 2 * bb.det(cc);
	return a - P(bb.y * dc - cc.y * db, cc.x * db - bb.x * dc) / d;
}

P othroCenter(P a, P b, P c) {
	P ba = b - a, ca = c - a, bc = b - c;
	double Y = ba.y * ca.y * bc.y,
	A = ca.x * ba.y - ba.x * ca.y,
	x0 = (Y + ca.x * ba.y * b.x - ba.x * ca.y * c.x) / A,
	y0 = -ba.x * (x0 - c.x) / ba.y + ca.y;
	return {x0, y0};
}
#include<bits/stdc++.h>
using namespace std;
struct Point{
    double x,y;
    Point(double _x=0,double _y=0):x(_x),y(_y){}
    Point operator + (Point p){return Point(x+p.x,y+p.y);}
    Point operator - (Point p){return Point(x-p.x,y-p.y);}
    Point operator * (double k){return Point(k*x,k*y);}
    Point operator / (double k){return Point(x/k,y/k);}
    double norm(){return x*x+y*y;};
    double abs(){return sqrt(norm());}
};
typedef Point Vector;
double dot(Vector a,Vector b)
{
    return a.x*b.x+a.y*b.y;
}
int main()
{
    Point p1,p2;
    scanf("%lf%lf%lf%lf",&p1.x,&p1.y,&p2.x,&p2.y);
    int q;
    scanf("%d",&q);
    while(q--){
        Point p;
        scanf("%lf%lf",&p.x,&p.y);
        double k1=dot(p2-p1,p-p1);
        double k2=(p2-p1).abs();
        k1/=k2;
        Point ans=(p2-p1)*(k1/k2);
        printf("%.10f %.10f\n",ans.x+p1.x,ans.y+p1.y);
    }
    return 0;
}
#include<bits/stdc++.h>
using namespace std;
struct Point{
    double x,y;
    Point(double _x=0,double _y=0):x(_x),y(_y){}
    Point operator + (Point p){return Point(x+p.x,y+p.y);}
    Point operator - (Point p){return Point(x-p.x,y-p.y);}
    Point operator * (double k){return Point(x*k,y*k);}
    Point operator / (double k){return Point(x/k,y/k);}
    double norm(){return x*x+y*y;}
    double abs(){return sqrt(norm());}
};
Point p1,p2,p0,p;
int q;
typedef Point Vector;
double dot(Vector a,Vector b)
{
    return a.x*b.x+a.y*b.y;
}
int main()
{
    scanf("%lf%lf%lf%lf",&p1.x,&p1.y,&p2.x,&p2.y);
    scanf("%d",&q);
    while(q--){
        scanf("%lf%lf",&p.x,&p.y);
        double k1=dot(p2-p1,p-p1);
        double k2=(p2-p1).abs();
        k1/=k2;
        Point len=(p2-p1)*(k1/k2);
        Point mid=p1+len;
        double x=2*mid.x-p.x,y=2*mid.y-p.y;
        printf("%.10f %.10f\n",x,y);
    }
    return 0;
}
#include<bits/stdc++.h>
using namespace std;
struct Point{
    double x,y;
    Point(double _x=0,double _y=0):x(_x),y(_y){}
    Point operator + (Point p){return Point(x+p.x,y+p.y);}
    Point operator - (Point p){return Point(x-p.x,y-p.y);}
    Point operator * (double k){return Point(x*k,y*k);}
    Point operator / (double k){return Point(x/k,y/k);}
    double norm(){return x*x+y*y;}
    double abs(){return sqrt(norm());}
};
Point p1,p2,p;
int q;
typedef Point Vector;
double dot(Vector a,Vector b){return a.x*b.x+a.y*b.y;}
double cross(Vector a,Vector b){return a.x*b.y-a.y*b.x;}
int main()
{
    scanf("%lf%lf%lf%lf",&p1.x,&p1.y,&p2.x,&p2.y);
    scanf("%d",&q);
    while(q--){
        scanf("%lf%lf",&p.x,&p.y);
        if(cross(p2-p1,p-p1)>0)printf("COUNTER_CLOCKWISE\n");
        else if(cross(p2-p1,p-p1)<0)printf("CLOCKWISE\n");
        else if(dot(p2-p1,p-p1)<0)printf("ONLINE_BACK\n");
        else if(((p-p1).abs()-(p2-p1).abs())>0)printf("ONLINE_FRONT\n");
        else printf("ON_SEGMENT\n");
    }
    return 0;
}
#include<bits/stdc++.h>
using namespace std;
const double eps=1e-10;
struct Point{
    double x,y;
    Point(double _x=0,double _y=0):x(_x),y(_y){}
    Point operator + (Point p){return Point(x+p.x,y+p.y);}
    Point operator - (Point p){return Point(x-p.x,y-p.y);}
    Point operator * (double k){return Point(x*k,y*k);}
    Point operator / (double k){return Point(x/k,y/k);}
    double norm(){return x*x+y*y;}
    double abs(){return sqrt(norm());}
};
Point p0,p1,p2,p3;
int q;
typedef Point Vector;
double dot(Vector a,Vector b){return a.x*b.x+a.y*b.y;}
double cross(Vector a,Vector b){return a.x*b.y-a.y*b.x;}
bool isParallel(Vector a,Vector b){return fabs(cross(a,b)-0.0)<=eps;}
bool isOrthogonal(Vector a,Vector b){return fabs(dot(a,b)-0.0)<=eps;}
int main()
{
    scanf("%d",&q);
    while(q--){
        scanf("%lf%lf%lf%lf%lf%lf%lf%lf",&p0.x,&p0.y,&p1.x,&p1.y,&p2.x,&p2.y,&p3.x,&p3.y);
        if(isParallel(p1-p0,p3-p2))printf("2\n");
        else if(isOrthogonal(p1-p0,p3-p2))printf("1\n");
        else printf("0\n");
    }
    return 0;
}
#include<bits/stdc++.h>
using namespace std;
const double eps=1e-10;
int sign(double x)
{
    if(fabs(x)<=eps)return 0;
    else if(x>0)return 1;
    return -1;
}
struct Point{
    double x,y;
    Point(double _x=0,double _y=0):x(_x),y(_y){}
    Point operator + (Point p){return Point(x+p.x,y+p.y);}
    Point operator - (Point p){return Point(x-p.x,y-p.y);}
    Point operator * (double k){return Point(x*k,y*k);}
    Point operator / (double k){return Point(x/k,y/k);}
    double norm(){return x*x+y*y;}
    double abs(){return sqrt(norm());}
};
Point p0,p1,p2,p3,p;
int q;
typedef Point Vector;
double dot(Vector a,Vector b){return a.x*b.x+a.y*b.y;}
double cross(Vector a,Vector b){return a.x*b.y-a.y*b.x;}
int ccw(Point a,Point b,Point c)
{
    Vector s1=b-a,s2=c-a;
    if(sign(cross(s1,s2))==-1)return -1;
    else if(sign(cross(s1,s2))==1)return 1;
    else if(sign(dot(s1,s2))==-1)return -1;
    else if(sign((c-a).abs()-(b-a).abs())==1)return 1;
    else return 0;
}
bool isIntersection()
{
    if(ccw(p0,p1,p2)*ccw(p0,p1,p3)<=0&&ccw(p2,p3,p0)*ccw(p2,p3,p1)<=0)return true;
    return false;
}
int main()
{
    scanf("%d",&q);
    while(q--){
        scanf("%lf%lf%lf%lf%lf%lf%lf%lf",&p0.x,&p0.y,&p1.x,&p1.y,&p2.x,&p2.y,&p3.x,&p3.y);
        if(isIntersection())printf("1\n");
        else printf("0\n");
    }
    return 0;
}
#include<bits/stdc++.h>
using namespace std;
const double eps=1e-10;
int sign(double x)
{
    if(fabs(x)<=eps)return 0;
    if(x>0)return 1;
    return -1;
}
struct Point{
    double x,y;
    Point(double _x=0,double _y=0):x(_x),y(_y){}
    Point operator + (Point p){return Point(x+p.x,y+p.y);}
    Point operator - (Point p){return Point(x-p.x,y-p.y);}
    Point operator * (double k){return Point(x*k,y*k);}
    Point operator / (double k){return Point(x/k,y/k);}
    double norm(){return x*x+y*y;}
    double abs(){return sqrt(norm());}
};
Point p0,p1,p2,p3;
int q;
typedef Point Vector;
double dot(Vector a,Vector b){return a.x*b.x+a.y*b.y;}
double cross(Vector a,Vector b){return a.x*b.y-a.y*b.x;}
struct Segment{
    Point p1,p2;
};
Point getCrossPoint(Segment a,Segment b)
{
    Vector base=b.p2-b.p1;
    double d1=fabs(cross(a.p1-b.p1,base));
    double d2=fabs(cross(a.p2-b.p1,base));
    double t=d1/(d1+d2);
    Point ans=a.p1+(a.p2-a.p1)*t;
    return ans;
}
int main()
{
    scanf("%d",&q);
    while(q--){
        scanf("%lf%lf%lf%lf%lf%lf%lf%lf",&p0.x,&p0.y,&p1.x,&p1.y,&p2.x,&p2.y,&p3.x,&p3.y);
        Point ans=getCrossPoint(Segment{p0,p1},Segment{p2,p3});
        printf("%.10f %.10f\n",ans.x,ans.y);
    }
    return 0;
}
#include<bits/stdc++.h>
using namespace std;
const double eps=1e-10;
int sign(double x)
{
    if(fabs(x)<=eps)return 0;
    if(x>0)return 1;
    return -1;
}
struct Point{
    double x,y;
    Point(double _x=0,double _y=0):x(_x),y(_y){}
    Point operator + (Point p){return Point(x+p.x,y+p.y);}
    Point operator - (Point p){return Point(x-p.x,y-p.y);}
    Point operator * (double k){return Point(x*k,y*k);}
    Point operator / (double k){return Point(x/k,y/k);}
    double norm(){return x*x+y*y;}
    double abs(){return sqrt(norm());}
};
Point p0,p1,p2,p3;
int q;
typedef Point Vector;
double dot(Vector a,Vector b){return a.x*b.x+a.y*b.y;}
double cross(Vector a,Vector b){return a.x*b.y-a.y*b.x;}
struct Segment{Point p1,p2;};
typedef Segment Line;
int ccw(Point a,Point b,Point c)
{
    if(sign(cross(c-a,b-a))==-1)return -1;
    else if(sign(cross(c-a,b-a))==1)return 1;
    else if(sign(dot(c-a,b-a))==-1)return -1;
    else if(sign((c-a).abs()-(b-a).abs())==1)return 1;
    else return 0;
}
bool isIntersection(Segment a,Segment b)
{
    if(ccw(a.p1,a.p2,b.p1)*ccw(a.p1,a.p2,b.p2)<=0&&ccw(b.p1,b.p2,a.p1)*ccw(b.p1,b.p2,a.p2)<=0)return true;
    else return false;
}
double getDistanceLP(Line a,Point p)
{
    return fabs(cross(p-a.p1,a.p2-a.p1)/(a.p2-a.p1).abs());
}
double getDistanceSP(Segment a,Point p)
{
    if(sign(dot(p-a.p1,a.p2-a.p1))==-1)return (p-a.p1).abs();
    else if(sign(dot(p-a.p2,a.p1-a.p2))==-1)return (p-a.p2).abs();
    return getDistanceLP(a,p);
}
double getDistance(Segment a,Segment b)
{
    if(isIntersection(a,b))return 0;
    return min(min(getDistanceSP(a,b.p1),getDistanceSP(a,b.p2)),min(getDistanceSP(b,a.p1),getDistanceSP(b,a.p2)));
}
int main()
{
    scanf("%d",&q);
    while(q--){
        scanf("%lf%lf%lf%lf%lf%lf%lf%lf",&p0.x,&p0.y,&p1.x,&p1.y,&p2.x,&p2.y,&p3.x,&p3.y);
        double ans=getDistance(Segment{p0,p1},Segment{p2,p3});
        printf("%.10f\n",ans);
    }
    return 0;
}
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e2+5;
const double eps=1e-10;
int sign(double x)
{
    if(fabs(x)<=eps)return 0;
    else if(x>0)return 1;
    return 0;
}
struct Point{
    double x,y;
    Point(double _x=0,double _y=0):x(_x),y(_y){}
    Point operator + (Point p){return Point(x+p.x,y+p.y);}
    Point operator - (Point p){return Point(x-p.x,y-p.y);}
    Point operator * (double k){return Point(x*k,y*k);}
    Point operator / (double k){return Point(x/k,y/k);}
    double norm(){return x*x+y*y;}
    double abs(){return sqrt(norm());}
};
Point p[maxn];
int n;
typedef Point Vector;
double dot(Vector a,Vector b){return a.x*b.x+a.y*b.y;}
double cross(Vector a,Vector b){return a.x*b.y-a.y*b.x;}
int main()
{
    scanf("%d",&n);
    for(int i=0;i<n;i++)scanf("%lf%lf",&p[i].x,&p[i].y);
    double ans=0;
    for(int i=1;i<=n;i++){
        ans+=cross(p[(i-1)%n],p[i%n])/2;
    }
    printf("%.1f\n",ans);
    return 0;
}
#include<bits/stdc++.h>
using namespace std;
const double eps=1e-10;
int sign(double x)
{
    if(fabs(x)<=eps)return 0;
    if(x>0)return 1;
    return -1;
}
struct Point{
    double x,y;
    Point(double _x=0,double _y=0):x(_x),y(_y){}
    Point operator + (Point p){return Point(x+p.x,y+p.y);}
    Point operator - (Point p){return Point(x-p.x,y-p.y);}
    Point operator * (double k){return Point(x*k,y*k);}
    Point operator / (double k){return Point(x/k,y/k);}
    double norm(){return x*x+y*y;}
    double abs(){return sqrt(norm());}
};
typedef Point Vector;
typedef vector<Point> polygon;
int n;
Point p;
polygon g;
double dot(Vector a,Vector b){return a.x*b.x+a.y*b.y;}
double cross(Vector a,Vector b){return a.x*b.y-a.y*b.x;}
const int COUNTER_CLOCKWISE = -1;   
const int CLOCKWISE = 1;        
const int ON_SEGMENT = 0;       
const int ONLINE_BACK = 2;       
const int ONLINE_FRONT = -2;     
int ccw(Point p0,Point p1,Point p2){
    Vector a=p1-p0;
    Vector b=p2-p0;
    if(cross(a,b)>eps) return COUNTER_CLOCKWISE;
    if(cross(a,b)<-eps) return CLOCKWISE;
    if(dot(a,b)<-eps) return ONLINE_BACK;
    if(a.norm()<b.norm()) return ONLINE_FRONT;
    return ON_SEGMENT;
}
int main()
{
    scanf("%d",&n);
    while(n--){
        scanf("%lf%lf",&p.x,&p.y);
        g.push_back(p);
    }
    g.push_back(g[0]);
    for(int i=0;i<g.size()-2;i++){
        if(ccw(g[i],g[i+1],g[i+2])==1){
            printf("0\n");
            return 0;
        }
    }
    printf("1\n");
    return 0;
}
#include<bits/stdc++.h>
using namespace std;
const double eps=1e-10;
int sign(double x)
{
    if(fabs(x)<=eps)return 0;
    if(x>0)return 1;
    return -1;
}
struct Point{
    double x,y;
    Point(double _x=0,double _y=0):x(_x),y(_y){}
    Point operator + (Point p){return Point(x+p.x,y+p.y);}
    Point operator - (Point p){return Point(x-p.x,y-p.y);}
    Point operator * (double k){return Point(x*k,y*k);}
    Point operator / (double k){return Point(x/k,y/k);}
    double norm(){return x*x+y*y;}
    double abs(){return sqrt(norm());}
};
typedef Point Vector;
typedef vector<Point> Polygon;
double dot(Vector a,Vector b){return a.x*b.x+a.y*b.y;}
double cross(Vector a,Vector b){return a.x*b.y-a.y*b.x;}
int n,q;
Polygon g;
Point p;
int contains()
{
    bool x=false;
    for(int i=0;i<g.size();i++){
        Vector a=g[i]-p,b=g[(i+1)%n]-p;
        if(sign(cross(a,b))==0&&dot(a,b)<=eps)return 1;
        if(a.y>b.y)swap(a,b);
        if(a.y<=eps&&b.y>eps&&sign(cross(a,b))==1)x=!x;
    }
    return x?2:0;
}
int main()
{
    scanf("%d",&n);
    for(int i=0;i<n;i++){
        scanf("%lf%lf",&p.x,&p.y);
        g.push_back(p);
    }
    scanf("%d",&q);
    for(int i=1;i<=q;i++){
        scanf("%lf%lf",&p.x,&p.y);
        printf("%d\n",contains());
    }
    return 0;
}
#include<bits/stdc++.h>
using namespace std;
const double eps=1e-10;
int sign(double x)
{
    if(fabs(x)<=eps)return 0;
    if(x>0)return 1;
    return -1;
}
struct Point{
    double x,y;
    Point(double _x=0,double _y=0):x(_x),y(_y){}
    Point operator + (Point p){return Point(x+p.x,y+p.y);}
    Point operator - (Point p){return Point(x-p.x,y-p.y);}
    Point operator * (double k){return Point(x*k,y*k);}
    Point operator / (double k){return Point(x/k,y/k);}
    double norm(){return x*x+y*y;}
    double abs(){return sqrt(norm());}
    bool operator < (const Point &p)const{return x!=p.x?x<p.x:y<p.y;}
};
typedef Point Vector;
typedef vector<Point> Polygon;
double dot(Vector a,Vector b){return a.x*b.x+a.y*b.y;}
double cross(Vector a,Vector b){return a.x*b.y-a.y*b.x;}
int ccw(Point p0,Point p1,Point p2)
{
    Vector a=p1-p0,b=p2-p0;
    if(sign(cross(a,b))==1)return 1;
    return 0;
}
int n;
Point p;
Polygon g,s,ans;
Polygon andrew()
{
    s=g;
    int n=s.size();
    if(n<3)return s;
    sort(s.begin(),s.end());
    Polygon u,l;
    u.push_back(s[0]);u.push_back(s[1]);
    l.push_back(s[n-1]);l.push_back(s[n-2]);
    for(int i=2;i<n;i++){
        for(int j=u.size();j>=2&&(ccw(u[j-2],u[j-1],s[i])==1);j--){
            u.pop_back();
        }
        u.push_back(s[i]);
    }
    for(int i=n-3;i>=0;i--){
        for(int j=l.size();j>=2&&(ccw(l[j-2],l[j-1],s[i])==1);j--){
            l.pop_back();
        }
        l.push_back(s[i]);
    }
    reverse(l.begin(),l.end());
    for(int i=u.size()-2;i>=1;i--){
        l.push_back(u[i]);
    }
    return l;
}
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++){
        scanf("%lf%lf",&p.x,&p.y);
        g.push_back(p);
    }
    ans=andrew();
    printf("%d\n",ans.size());
    int num=0,len=ans.size();
    while(1){
        if(ans[num%len].y<=ans[(num+1)%len].y){
            for(int i=num%len;i<len;i++){
                printf("%.0f %.0f\n",ans[i].x,ans[i].y);
            }
            for(int i=0;i<num%len;i++){
                printf("%.0f %.0f\n",ans[i].x,ans[i].y);
            }
            break;
        }
        num++;
    }
    return 0;
}
#include<bits/stdc++.h>
using namespace std;
const double eps=1e-10;
int sign(double x)
{
    if(fabs(x)<=eps)return 0;
    if(x>0)return 1;
    return -1;
}
struct Point{
    double x,y;
    Point(double _x=0,double _y=0):x(_x),y(_y){}
    Point operator + (Point p){return Point(x+p.x,y+p.y);}
    Point operator - (Point p){return Point(x-p.x,y-p.y);}
    Point operator * (double k){return Point(x*k,y*k);}
    Point operator / (double k){return Point(x/k,y/k);}
    double norm(){return x*x+y*y;}
    double abs(){return sqrt(norm());}
    bool operator < (const Point &p)const{return x!=p.x?x<p.x:y<p.y;}
};
typedef Point Vector;
typedef vector<Point> Polygon;
double dot(Vector a,Vector b){return a.x*b.x+a.y*b.y;}
double cross(Vector a,Vector b){return a.x*b.y-a.y*b.x;}
int ccw(Point p0,Point p1,Point p2)
{
    Vector a=p1-p0,b=p2-p0;
    if(sign(cross(a,b))==1)return 1;
    return 0;
}
int n;
Point p;
Polygon g,s,ans;
double Area(Point a,Point b,Point c)
{
    Vector x1=b-a,y1=c-a;
    return cross(x1,y1);
}
Polygon andrew()
{
    s=g;
    int n=s.size();
    sort(s.begin(),s.end());
    Polygon u;
    for(int i=0;i<n;i++){
        for(int j=u.size();j>=2&&sign(Area(u[j-2],u[j-1],s[i]))>=0;j--){
            u.pop_back();
        }
        u.push_back(s[i]);
    }
    int tmp=u.size()+1;
    for(int i=n-2;i>=0;i--){
        for(int j=u.size();j>=tmp&&sign(Area(u[j-2],u[j-1],s[i]))>=0;j--){
            u.pop_back();
        }
        u.push_back(s[i]);
    }
    if(n>1)u.pop_back();
    reverse(u.begin(),u.end());
    return u;
}
double rc()
{
    double res=0;
    int n=ans.size();
    int k=1;
    for(int i=0;i<n;i++){
        while(sign(Area(ans[i],ans[(i+1)%n],ans[(k+1)%n])-Area(ans[i],ans[(i+1)%n],ans[k%n]))==1)k=(k+1)%n;
        res=max(res,(ans[i]-ans[k]).abs());
    }
    return res;
}
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++){
        scanf("%lf%lf",&p.x,&p.y);
        g.push_back(p);
    }
    ans=andrew();
    printf("%.10f\n",rc());
    return 0;
}
5
1 -1
5 1
3 4
-1 3
-2 0
1
7 -2 8 -3
#include<bits/stdc++.h>
using namespace std;
#define long double double
const double eps=1e-10;
int sign(double x)
{
    if(fabs(x)<=eps)return 0;
    if(x>0)return 1;
    return -1;
}
struct Point{
    double x,y;
    Point(double _x=0,double _y=0):x(_x),y(_y){}
    Point operator + (Point p){return Point(x+p.x,y+p.y);}
    Point operator - (Point p){return Point(x-p.x,y-p.y);}
    Point operator * (double k){return Point(x*k,y*k);}
    Point operator / (double k){return Point(x/k,y/k);}
    double norm(){return x*x+y*y;}
    double abs(){return sqrt(norm());}
};
typedef Point Vector;
typedef vector<Point> Polygon;
double dot(Vector a,Vector b){return a.x*b.x+a.y*b.y;}
double cross(Vector a,Vector b){return a.x*b.y-a.y*b.x;}
struct Segment{Point p1,p2;};
typedef Segment Line;
int n,q;
Point p,a,b;
Polygon g;
int ccw(Point p0,Point p1,Point p2)
{
    Vector v1=p1-p0,v2=p2-p0;
    if(sign(cross(v1,v2))==1)return -1;
    if(sign(cross(v1,v2))==-1)return 1;
    return 0;
}
Point getCrossPoint(Segment s1,Line s2)
{
    Vector base=s2.p2-s2.p1;
    double d1=abs(cross(base,s1.p1-s2.p1));
    double d2=abs(cross(base,s1.p2-s2.p1));
    double t=d1/(d1+d2);
    return s1.p1+(s1.p2-s1.p1)*t;
}
int main()
{
    scanf("%d",&n);
    for(int i=0;i<n;i++){
        scanf("%lf%lf",&p.x,&p.y);
        g.push_back(p);
    }
    scanf("%d",&q);
    for(int i=0;i<q;i++){
        scanf("%lf%lf%lf%lf",&a.x,&a.y,&b.x,&b.y);
        Polygon tmp;
        for(int i=0;i<n;i++){
            if(ccw(a,b,g[i])!=1)tmp.push_back(g[i]);
            if(ccw(a,b,g[i])*ccw(a,b,g[(i+1)%n])==-1)tmp.push_back(getCrossPoint(Segment{g[i],g[(i+1)%n]},Line{a,b}));
        }
        int len=tmp.size();
        double ans=0;
        for(int i=0;i<len;i++){
            Point t1=tmp[i],t2=tmp[(i+1)%len];
            ans+=cross(t1,t2);
        }
        ans/=2.0;
        printf("%.8f\n",ans);
    }
    return 0;
}
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+5;
const double eps=1e-10;
const double inf=1e9;
int sign(double x)
{
    if(fabs(x)<=eps)return 0;
    if(x>0)return 1;
    return -1;
}
struct Point{
    double x,y;
    Point(double _x=0,double _y=0):x(_x),y(_y){}
    Point operator + (Point p){return Point(x+p.x,y+p.y);}
    Point operator - (Point p){return Point(x-p.x,y-p.y);}
    Point operator * (double k){return Point(x*k,y*k);}
    Point operator / (double k){return Point(x/k,y/k);}
    double norm(){return x*x+y*y;}
    double abs(){return sqrt(norm());}
    bool operator < (const Point &p)const{return x<p.x;}
};
bool cmpy(Point p0,Point p1){return p0.y<p1.y;}
int n;
Point a[maxn],b[maxn];
double dis(Point p0,Point p1){return sqrt((p0.x-p1.x)*(p0.x-p1.x)+(p0.y-p1.y)*(p0.y-p1.y));};
double Divide_Conquer(int l,int r)
{
    if(l==r)return inf;
    if(l+1==r)return dis(a[l],a[r]);
    int mid=(l+r)>>1;
    double ans=min(Divide_Conquer(l,mid),Divide_Conquer(mid+1,r));
    int len=0;
    for(int i=l;i<=r;i++)if(fabs(a[mid].x-a[i].x)<=ans)b[len++]=a[i];
    sort(b,b+len,cmpy);
    for(int i=0;i<len;i++){
        for(int j=i+1;j<len;j++){
            if(b[j].y-b[i].y>ans)break;
            ans=min(ans,dis(b[i],b[j]));
        }
    }
    return ans;
}
int main()
{
    scanf("%d",&n);
    for(int i=0;i<n;i++)scanf("%lf%lf",&a[i].x,&a[i].y);
    sort(a,a+n);
    printf("%.10f\n",Divide_Conquer(0,n-1));
    return 0;
}
#include<bits/stdc++.h>
using namespace std;
int n,m,cnt,ans,HASH[200001],tr[200001];
struct point{int x,y;}a[200001];
struct seg{int k,x,y,r;}s[2000001];
inline bool cmp3(seg a,seg b){
    if(a.y==b.y)return a.k>b.k;
    return a.y<b.y;
}
int find(int x)
{
    int l=0,r=m+1;
    while(l+1<r)
    {
        int mid=(l+r)>>1;
        if(HASH[mid]>=x)r=mid;
        else l=mid;
    }
    return r;
}
void insert(int k,int l,int r,int t)//0横线,1竖线
{
    if(!k){s[++cnt].x=find(l);s[cnt].r=find(r);s[cnt].y=t;s[cnt].k=0;}
    else{
        s[++cnt].x=find(t);s[cnt].y=l;s[cnt].k=1;
        s[++cnt].x=find(t);s[cnt].y=r;s[cnt].k=-1;
    }
}
void update(int x,int y)
{
    while(x<2e5)
    {
        tr[x]+=y;
        x+=x&(-x);
    }
}
int ask(int x)
{
    int s=0;
    while(x){
        s+=tr[x];
        x-=x&(-x);
    }
    return s;
}
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=2*n;i++){
        scanf("%d%d",&a[i].x,&a[i].y);
        HASH[i]=a[i].x;
    }
    sort(HASH+1,HASH+2*n+1);
    m=unique(HASH+1,HASH+2*n+1)-(HASH+1);
    for(int i=1;i<2*n;i+=2){
        if(a[i].x==a[i+1].x){
            if(a[i].y>a[i+1].y)swap(a[i],a[i+1]);
            insert(1,a[i].y,a[i+1].y,a[i].x);
        }else{
            if(a[i].x>a[i+1].x)swap(a[i],a[i+1]);
            insert(0,a[i].x,a[i+1].x,a[i].y);
        }
    }
    sort(s+1,s+cnt+1,cmp3);
    for(int i=1;i<=cnt;i++){
        if(!s[i].k)ans+=ask(s[i].r)-ask(s[i].x-1);
        else update(s[i].x,s[i].k);
    }
    printf("%d\n",ans);
    return 0;
}
#include<bits/stdc++.h>
using namespace std;
const double eps=1e-10;
int sign(double x)
{
    if(fabs(x)<=eps)return 0;
    if(x>0)return 1;
    return -1;
}
struct Point{
    double x,y;
    Point(double _x=0,double _y=0):x(_x),y(_y){}
    Point operator + (Point p){return Point(x+p.x,y+p.y);}
    Point operator - (Point p){return Point(x-p.x,y-p.y);}
    Point operator * (double k){return Point(x*k,y*k);}
    Point operator / (double k){return Point(x/k,y/k);}
    double norm(){return x*x+y*y;}
    double abs(){return sqrt(norm());}
};
typedef Point Vector;
double dot(Vector a,Vector b){return a.x*b.x+a.y*b.y;}
double cross(Vector a,Vector b){return a.x*b.y-a.y*b.x;}
double getDistance(Point a,Point b){return (a-b).abs();}
struct Circle{
    Point c;
    double r;
    Circle(Point _c=Point(),double _r=0):c(_c),r(_r){}
};
const int SEPARATION=4;
const int EXTERNAL_CUT=3;
const int INTERSECTION=2;
const int INTERNAL_CUT=1;
const int INCLUDE=0;
int getCircleToCircle(Circle c1,Circle c2)
{
    double dis=getDistance(c1.c,c2.c);
    if(sign(c1.r+c2.r-dis)==-1)return SEPARATION;
    else if(sign(c1.r+c2.r-dis)==0)return EXTERNAL_CUT;
    else{
        if(sign(fabs(c1.r-c2.r)-dis)==0)return INTERNAL_CUT;
        else if(sign(fabs(c1.r-c2.r)-dis)==1)return INCLUDE;
        return INTERSECTION;
    }
}
int main()
{
    double x,y,r;
    scanf("%lf%lf%lf",&x,&y,&r);
    Circle c1{Point(x,y),r};
    scanf("%lf%lf%lf",&x,&y,&r);
    Circle c2{Point(x,y),r};
    printf("%d\n",getCircleToCircle(c1,c2));
    return 0;
}
#include<bits/stdc++.h>
using namespace std;
const double eps=1e-10;
int sign(double x)
{
    if(fabs(x)<=eps)return 0;
    if(x>0)return 1;
    return -1;
}
struct Point{
    double x,y;
    Point(double _x=0,double _y=0):x(_x),y(_y){}
    Point operator + (Point p){return Point(x+p.x,y+p.y);}
    Point operator - (Point p){return Point(x-p.x,y-p.y);}
    Point operator * (double k){return Point(x*k,y*k);}
    Point operator / (double k){return Point(x/k,y/k);}
    double norm(){return x*x+y*y;}
    double abs(){return sqrt(norm());}
};
typedef Point Vector;
double dot(Vector a,Vector b){return a.x*b.x+a.y*b.y;}
double cross(Vector a,Vector b){return a.x*b.y-a.y*b.x;}
struct Segment{Point p1,p2;};
typedef Segment Line;
struct Circle{
    Point c;
    double r;
    Circle(Point _c=Point(),double _r=0):c(_c),r(_r){}
};
Point project(Segment s,Point p)
{
    Vector base=s.p2-s.p1;
    double r=dot(p-s.p1,base)/base.norm();
    return s.p1+base*r;
}
pair<Point,Point>getCrossPoints(Circle c,Line l)
{
    Point pr=project(l,c.c);
    Vector e=(l.p2-l.p1)/(l.p2-l.p1).abs();
    double base=sqrt(c.r*c.r-(pr-c.c).norm());
    return make_pair(pr+e*base,pr-e*base);
}
int main()
{
    double x,y,r;
    scanf("%lf%lf%lf",&x,&y,&r);
    Circle c1(Point(x,y),r);
    int q;
    scanf("%d",&q);
    for(int i=1;i<=q;i++){
        double a,b,c,d;
        scanf("%lf%lf%lf%lf",&a,&b,&c,&d);
        Line l;l.p1=Point(a,b);l.p2=Point(c,d);
        pair<Point,Point>ans=getCrossPoints(c1,l);
        if(ans.first.x>ans.second.x)swap(ans.first,ans.second);
        else if(ans.first.x==ans.second.x&&ans.first.y>ans.second.y)swap(ans.first,ans.second);
        printf("%.10f %.10f %.10f %.10f\n",ans.first.x,ans.first.y,ans.second.x,ans.second.y);
    }
    return 0;
}
#include<bits/stdc++.h>
using namespace std;
const double eps=1e-10;
int sign(double x)
{
    if(fabs(x)<=eps)return 0;
    if(x>0)return 1;
    return -1;
}
struct Point{
    double x,y;
    Point(double _x=0,double _y=0):x(_x),y(_y){}
    Point operator + (Point p){return Point(x+p.x,y+p.y);}
    Point operator - (Point p){return Point(x-p.x,y-p.y);}
    Point operator * (double k){return Point(x*k,y*k);}
    Point operator / (double k){return Point(x/k,y/k);}
    double norm(){return x*x+y*y;}
    double abs(){return sqrt(norm());}
};
typedef Point Vector;
double dot(Vector a,Vector b){return a.x*b.x+a.y*b.y;}
double cross(Vector a,Vector b){return a.x*b.y-a.y*b.x;}
struct Circle{
    Point c;
    double r;
    Circle(Point _c=Point(),double _r=0):c(_c),r(_r){}
};
double arg(Vector p){
    return atan2(p.y,p.x);
}
Vector polar(double r,double a){
    return Point(cos(a)*r,sin(a)*r);
}
pair<Point,Point> getCrossPoints(Circle c1,Circle c2){
    double d=(c1.c-c2.c).abs();
    double a=acos((c1.r*c1.r+d*d-c2.r*c2.r)/(2*c1.r*d));
    double t=arg(c2.c-c1.c);
    return make_pair(c1.c+polar(c1.r,t+a),c1.c+polar(c1.r,t-a));
}
int main(){
    double r1,r2;
    Point p1,p2;
    scanf("%lf%lf%lf",&p1.x,&p1.y,&r1);
    scanf("%lf%lf%lf",&p2.x,&p2.y,&r2);
    Circle c1(p1,r1);
    Circle c2(p2,r2);
    pair<Point,Point> ans=getCrossPoints(c1,c2);
    if(ans.first.x>ans.second.x) swap(ans.first,ans.second);
    else if(ans.first.x==ans.second.x&&ans.first.y>ans.second.y) swap(ans.first,ans.second);
    printf("%.10f %.10f %.10f %.10f\n",ans.first.x,ans.first.y,ans.second.x,ans.second.y);
    return 0;
}
#include<bits/stdc++.h>
using namespace std;
const double eps=1e-10;
int sign(double x){
    if(fabs(x)<=eps)return 0;return x>0?1:0;}
struct Point{
    double x,y;
    Point(double _x=0,double _y=0):x(_x),y(_y){}
    Point operator + (Point p){return Point(x+p.x,y+p.y);}
    Point operator - (Point p){return Point(x-p.x,y-p.y);}
    Point operator * (double k){return Point(x*k,y*k);}
    Point operator / (double k){return Point(x/k,y/k);}
    double norm(){return x*x+y*y;}
    double abs(){return sqrt(norm());}
    bool operator < (const Point &p){return x<p.x||(x==p.x&&y<p.y);}
};
typedef Point Vector;
double dot(Vector a,Vector b){return a.x*b.x+a.y*b.y;}
double cross(Vector a,Vector b){return a.x*b.y-a.y*b.x;}
struct Circle{
    Point c;
    double r;
    Circle(Point _c=Point(),double _r=0):c(_c),r(_r){}
    Point point(double a){return Point(c.x+cos(a)*r,c.y+sin(a)*r);}
};
Point rotate(Point base,Point a,double r)
{
    Point b=a-base;
    a.x=b.x*cos(r)-b.y*sin(r);
    a.y=b.x*sin(r)+b.y*cos(r);
    a=a+base;
    return a;
}
pair<Point,Point>getTangent(Circle c,Point p)
{
    Vector v=p-c.c;
    double r=acos(c.r/v.abs());
    v=v*c.r/v.abs();
    Point p1=rotate(c.c,c.c+v,r);
    Point p2=rotate(c.c,c.c+v,-r);
    return make_pair(p1,p2);
}
int main()
{
    Point p;
    double x,y,r;
    cin>>p.x>>p.y>>x>>y>>r;
    Circle c(Point(x,y),r);
    pair<Point,Point>ans=getTangent(c,p);
    if(ans.second<ans.first)swap(ans.first,ans.second);
    printf("%.10f %.10f\n%.10f %.10f\n",ans.first.x,ans.first.y,ans.second.x,ans.second.y);
    return 0;
}
#include<bits/stdc++.h>
#define PI M_PI
using namespace std;
const double EPS=1e-10;
inline 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){}
    Point operator + (Point p) { return Point(x+p.x,y+p.y); }
    Point operator - (Point p) { return Point(x-p.x,y-p.y); }
    Point operator * (double k) { return Point(k*x,k*y); }
    Point operator / (double k) { return Point(x/k,y/k); }
    inline double abs(){ return sqrt(norm()); }
    inline double norm() { return x*x+y*y; }
    bool operator < (const Point &p)const{return sign(x-p.x)<0||sign(x-p.x)==0&&sign(y-p.y)<0;}
    bool operator == (const Point & p)const{fabs(x-p.x)<EPS&&fabs(y-p.y)<EPS;}
};
typedef Point Vector;
double dot(Vector a,Vector b){return a.x*b.x+a.y*b.y;}
double cross(Vector a,Vector b){return a.x*b.y-a.y*b.x;}
struct Circle{
    Point c;
    double r;
    Circle(Point c = Point() ,double r = 0.0 ):c(c),r(r){}
    Point point(double a){return Point(c.x+r*cos(a),c.y+r*sin(a));}
};
Point rotate(Point base,Point a,double r){     
  Point b=a-base;
  a.x=b.x*cos(r)-b.y*sin(r);         
  a.y=b.x*sin(r)+b.y*cos(r);
  a=a+base;
  return a;
}
pair<Point,Point> getTangent(Circle c,Point p){
  Vector v=p-c.c;
  double r=acos(c.r/v.abs());
  v=v*c.r/v.abs();
  Point p1=rotate(c.c,c.c+v,r);
  Point p2=rotate(c.c,c.c+v,2*PI-r);
  return make_pair(p1,p2);
}
int getTangents(Circle A, Circle B, Point *a, Point *b){
    int cnt = 0;       
    if(sign(A.r - B.r) < 0){swap(A, B);swap(a, b);}
    double d = sqrt((A.c.x - B.c.x) * (A.c.x - B.c.x) + (A.c.y - B.c.y) * (A.c.y - B.c.y));     
    double rdiff = A.r - B.r;     
    double rsum = A.r + B.r;    
    if(sign(d - rdiff) < 0) return 0;        
    double base = atan2(B.c.y - A.c.y, B.c.x - A.c.x);     
    if(sign(d) == 0) return -1;      
    if(sign(d - rdiff) == 0){     
        a[cnt] = b[cnt] = A.point(base);
        cnt++;
        return 1;
    }
    double ang = acos((A.r - B.r) / d);
    a[cnt] = A.point(base + ang); b[cnt] = B.point(base + ang); cnt++;     
    a[cnt] = A.point(base - ang); b[cnt] = B.point(base - ang); cnt++;   
    if(sign(d - rsum) == 0){     
        a[cnt] = b[cnt] = A.point(base);
        cnt++;
    }else if(sign(d - rsum) > 0){      
        double ang = acos((A.r + B.r) / d);
        a[cnt] = A.point(base + ang); b[cnt] = B.point(PI + base + ang); cnt++;
        a[cnt] = A.point(base - ang); b[cnt] = B.point(PI + base - ang); cnt++;
    }
    return cnt;

}


int main(){
    Circle A,B;
    Point a[5],b[5];
    while(scanf("%lf%lf%lf%lf%lf%lf",&A.c.x,&A.c.y,&A.r,&B.c.x,&B.c.y,&B.r)!=EOF){
        bool flag=0;
        if(sign(A.r - B.r) < 0) flag=1;
        int cnt=getTangents(A,B,a,b);
        if(cnt==-1||cnt==0) continue;
        vector<Point> v;
        for(int i=0;i<cnt;i++){
            v.push_back(a[i]);
        }
        sort(v.begin(),v.end());
        for(int i=0;i<cnt;i++){
            printf("%.10f %.10f\n",v[i].x,v[i].y);
        }
    }
    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值