未经过题目测试。。。

#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<string>
#include<cmath>
#include<queue>
#include<map>
#include<vector>
#define ll long long
#define llu unsigned ll
using namespace std;

const double eps=1e-8;
const double dnf=1e20;
const double pi=acos(-1.0);
const int maxp=1010;

//浮点型数值是否为0
int sgn(double x)
{
    if(abs(x)<eps) return 0;
    if(x<0) return -1;
    return 1;
}

struct Point3
{
    double x,y,z;
    Point3(double xx=0,double yy=0,double zz=0)
    {
        x=xx,y=yy,z=zz;
    }

    void input(void)
    {
        scanf("%lf%lf%lf",&x,&y,&z);
    }
    void output(void)
    {
        printf("%.2f %.2f %.2f\n",x,y,z);
    }

    double len(void)
    {
        return sqrt(x*x+y*y+z*z);
    }

    double len2(void)
    {
        return x*x+y*y+z*z;
    }

    double dis(const Point3 &b) const
    {
        return sqrt((x-b.x)*(x-b.x)+(y-b.y)*(y-b.y)+(z-b.z)*(z-b.z));
    }

    bool operator ==(const Point3 &b) const
    {
        return sgn(x-b.x)==0&&sgn(y-b.y)==0&&sgn(z-b.z)==0;
    }

    bool operator <(const Point3 &b) const
    {
        if(sgn(x-b.x)!=0) return x<b.x;
        if(sgn(y-b.y)!=0) return y<b.y;
        return sgn(z-b.z)<0;
    }

    Point3 operator + (const Point3 &b) const
    {
        return Point3(x+b.x,y+b.y,z+b.z);
    }
    Point3 operator - (const Point3 &b) const
    {
        return Point3(x-b.x,y-b.y,z-b.z);
    }
    Point3 operator * (const double &k) const
    {
        return Point3(x*k,y*k,z*k);
    }
    Point3 operator / (const double &k) const
    {
        return Point3(x/k,y/k,z/k);
    }

    Point3 operator ^ (const Point3 &b) const
    {
        return Point3(y*b.z-z*b.y,z*b.x-x*b.z,x*b.y-y*b.x);
    }
    double operator * (const Point3 &b) const
    {
        return x*b.x+y*b.y+z*b.z;
    }
    double rad(Point3 a,Point3 b)
    {
        Point3 p=(*this);
        return acos(((a-p)*(b-p))/(a.dis(p)*b.dis(p)));
    }
    Point3 turn_to_r(double r)
    {
        double l=len();
        if(!sgn(l)) return *this;
        r/=l;
        return Point3(x*r,y*r,z*r);
    }

};

struct Line3
{
    Point3 s,e;
    Line3(){}
    Line3(Point3 ss,Point3 ee)
    {
        s=ss,e=ee;
    }

    void input(void)
    {
        s.input();
        e.input();
    }

    void output(void)
    {
        s.output();
        e.output();
    }

    bool operator == (const Line3 v)
    {
        return (s==v.s)&&(e==v.e);
    }

    double len(void)
    {
        return s.dis(e);
    }

    double dis_point_to_line(Point3 p)
    {
        return ((e-s)^(p-s)).len()/s.dis(e);
    }

    double dis_point_to_seg(Point3 p)
    {
        if(sgn((p-s)*(e-s))<0||sgn((p-e)*(s-e))<0)
            return min(p.dis(s),p.dis(e));
        return dis_point_to_line(p);
    }
    Point3 point_prog_line(Point3 p)
    {
        return s+(((e-s)*((e-s)*(p-s)))/((e-s).len2()));
    }
    //P绕此向量逆时针转angle角度
    Point3 turn_line_angle(Point3 p,double angle)
    {
        if(sgn(((s-p)^(e-p)).len())==0) return p;
        Point3 f1=(e-s)^(p-s);
        Point3 f2=(e-s)^f1;
        double len=((s-p)^(e-p)).len()/s.dis(e);
        f1=f1.turn_to_r(len);
        f2=f2.turn_to_r(len);
        Point3 h=p+f2;
        Point3 pp=h+f1;
        return h+((p-h)*cos(angle))+((pp-h)*sin(angle));
    }

    bool point_is_on_seg(Point3 p)
    {
        return sgn(((s-p)^(e-p)).len())==0&&sgn((s-p)*(e-p))==0;
    }
};

struct Plane
{
    Point3 a,b,c,o;//o是法向量
    Plane(){}

    Point3 pvec(void)
    {
        return (b-a)^(c-a);
    }

    Plane(Point3 aa,Point3 bb,Point3 cc)
    {
        a=aa,b=bb,c=cc,o=pvec();
    }
    //ax+by+cz+d=0;
    Plane(double aa,double bb,double cc,double dd)
    {
        o=Point3(aa,bb,cc);
        if(sgn(aa)!=0)
            a=Point3((-dd-cc-bb)/aa,1,1);
        else if(sgn(bb)!=0)
            a=Point3(1,(-dd-cc-aa)/bb,1);
        else if(sgn(cc)!=0)
            a=Point3(1,1,(-dd-aa-bb)/cc);
    }
    //点在平面上的判断
    bool point_is_on_plane(Point3 p)
    {
        return sgn((p-a)*o)==0;
    }
    //两平面夹角
    double angle_plane(Plane f)
    {
        return acos(o*f.o)/(o.len()*f.o.len());
    }
    //平面和直线的交点,返回值是交点个数
    int cross_line_plane(Line3 u,Point3 &p)
    {
        double x=o*(u.e-a);
        double y=o*(u.s-a);
        double d=x-y;
        if(sgn(d)==0) return 0;
        p=((u.s*x)-(u.e*y))/d;
        return 1;
    }
    //点到平面最近点 (也就是投影)
    Point3 point_to_plane(Point3 p)
    {
        Line3 u=Line3(p,p+o);
        cross_line_plane(u,p);
        return p;
    }
    //平面和平面的交线
    int cross_plane_plane(Plane f,Line3 &u)
    {
        Point3 oo=o^f.o;
        Point3 v=o^oo;
        double d=abs(f.o*v);
        if(sgn(d)==0) return 0;
        Point3 q=a+(v*(f.o*(f.a-a))/d);
        u=Line3(q,q+oo);
        return 1;
    }

};

int main(void)
{
    return 0;
}